├── renovate.json ├── .gitignore ├── library.js ├── package.json ├── index.js ├── plugin.js ├── README.md ├── providers └── google-sheet-provider.js └── yarn.lock /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "config:base" 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # dependencies 2 | node_modules 3 | 4 | # Mac files 5 | .DS_Store 6 | /**/*.DS_Store 7 | -------------------------------------------------------------------------------- /library.js: -------------------------------------------------------------------------------- 1 | const path = require('path') 2 | 3 | function loadProvider(providerName) { 4 | return require('./providers/' + providerName + '-provider'); 5 | } 6 | 7 | async function importI18n({ path, conf, log }) { 8 | const provider = loadProvider(conf.provider) 9 | 10 | return provider.importI18n({ path, conf, log }) 11 | } 12 | 13 | module.exports = { 14 | importI18n 15 | } 16 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@nuxtjs/dynamic-i18n", 3 | "version": "2.0.0", 4 | "license": "MIT", 5 | "repository": "https://github.com/nuxt/modules", 6 | "homepage": "https://github.com/nuxt/modules/tree/master/modules/dynamic-i18n", 7 | "publishConfig": { 8 | "access": "public" 9 | }, 10 | "main": "index.js", 11 | "dependencies": { 12 | "google-spreadsheet": "^3.0.10", 13 | "lodash": "^4.17.5", 14 | "vue-i18n": "^7.6.0" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | const path = require('path') 2 | const library = require('./library') 3 | 4 | const defaults = { 5 | provider: 'google-sheet', 6 | languages: ['en'], 7 | fallbackLocale: 'en', 8 | outputFilePrefix: 'locale', 9 | maxAge: 1000 * 60 * 60, 10 | localeNamespaceStore: 'i18n', 11 | staticFolder: 'i18n' 12 | } 13 | 14 | async function importI18n({ conf, log, error }) { 15 | return library.importI18n({ 16 | path: conf.path, 17 | conf, 18 | log, 19 | error 20 | }) 21 | } 22 | 23 | module.exports = async function nuxtDynamicI18n(_moduleOptions) { 24 | // Set default translate path into static directory 25 | defaults.path = path.join(this.nuxt.options.srcDir, this.nuxt.options.dir.static, defaults.staticFolder) 26 | // Get options from module injection 27 | const conf = Object.assign(defaults, this.options.dynamicI18n, _moduleOptions) 28 | 29 | const importOptions = { 30 | conf, 31 | log: console.log, 32 | error: console.error 33 | } 34 | 35 | // Load translates from provider 36 | await importI18n(importOptions) 37 | 38 | this.addPlugin({ 39 | src: path.resolve(__dirname, 'plugin.js'), 40 | options: conf 41 | }) 42 | 43 | if (conf.maxAge) setInterval(() => importI18n(importOptions), conf.maxAge) 44 | } 45 | 46 | module.exports.meta = require('./package.json') 47 | -------------------------------------------------------------------------------- /plugin.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import VueI18n from 'vue-i18n' 3 | import axios from 'axios' 4 | 5 | Vue.use(VueI18n) 6 | 7 | function generateUrl(language) { 8 | const path = '/i18n/<%= options.outputFilePrefix %>' + '-' + language + '.json' 9 | 10 | let url = path 11 | const host = process.env.HOST || process.env.npm_package_config_nuxt_host || 'localhost' 12 | const port = process.env.PORT || process.env.npm_package_config_nuxt_port || 3000 13 | 14 | return 'http://' + host + ':' + port + url 15 | } 16 | 17 | export default async ({ app, store, beforeNuxtRender }) => { 18 | const languages = '<%= options.languages %>'.split(',') 19 | let languagesSrc = {} 20 | 21 | // On server side 22 | if (process.server) { 23 | for (const language of languages) { 24 | const { data } = await axios(generateUrl(language)) 25 | 26 | languagesSrc[language] = data 27 | } 28 | 29 | beforeNuxtRender(({ nuxtState }) => { 30 | nuxtState.i18n = languagesSrc 31 | }) 32 | } 33 | 34 | // On client side 35 | if (process.client) { 36 | languagesSrc = window.__NUXT__.i18n 37 | } 38 | 39 | // Set i18n instance on app 40 | app.i18n = new VueI18n({ 41 | locale: store.state['<%= options.localeNamespaceStore %>'].locale, 42 | fallbackLocale: '<%= options.fallbackLocale %>', 43 | messages: languagesSrc 44 | }) 45 | } 46 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Dynamic I18n v2.0.0 2 | [![npm](https://img.shields.io/npm/dt/@nuxtjs/dynamic-i18n.svg?style=flat-square)](https://www.npmjs.com/package/@nuxtjs/dynamic-i18n) 3 | [![npm (scoped with tag)](https://img.shields.io/npm/v/@nuxtjs/dynamic-i18n/latest.svg?style=flat-square)](https://www.npmjs.com/package/@nuxtjs/dynamic-i18n) 4 | 5 | **Dynamic i18n** is a tool to import your i18n and inject it in your vue-i18n instance 6 | 7 | This module automatically import your translate file from a specific provider. 8 | 9 | # RoadMap 10 | - Integrate [https://github.com/nuxt-community/nuxt-i18n](nuxt-i18n) plugin 11 | 12 | # Supported providers 13 | * Google sheets, see example of file [here](https://docs.google.com/spreadsheets/d/1dBsD-EsKb1mHvq4P2Zm4DcOPK2szuxqkkvnTsmbkYhc/edit?usp=sharing) 14 | 15 | ## Setup 16 | - Add `@nuxtjs/dynamic-i18n` dependency using yarn or npm to your project 17 | - Add `@nuxtjs/dynamic-i18n` to `modules` section of `nuxt.config.js` 18 | ```js 19 | modules: [ 20 | '@nuxtjs/dynamic-i18n' 21 | ], 22 | dynamicI18n: { 23 | languages: ['en', 'fr'], 24 | providerKey: '1dBsD-EsKb1mHvq4P2Zm4DcOPK2szuxqkkvnTsmbkYhc', 25 | credentials: {...}, 26 | ...Options 27 | } 28 | ``` 29 | 30 | ## Options 31 | 32 | | key | Required | Default | Description | 33 | |-----|----------|---------|-------------| 34 | | languages | **Required** | `[]` | Contain all the locales we want to import. | 35 | | provider-key | **Required** | `''` | The identifier for the source of the data stored. | 36 | | credentials | **Required** | `{}` | Configuration for the provider. | 37 | | id | Optional | None | id of the active document. Use gid for google sheet url to get active tab id | 38 | | maxAge | Optional | `1000 * 60 * 60` | Max age of translate files (60 minutes), use 0 to disable it 39 | | fallbackLocale | Optional | `'en'` | Default language if not founded from the store | 40 | | localeNamespaceStore | Optional | `'i18n'` | Default namespace of i18n locale store. see example of store [here](https://github.com/nuxt/nuxt.js/blob/dev/examples/i18n/store/index.js)| 41 | | outputFilePrefix | Optional | `'locale'` | Prefix of the output file like : {{outputFilePrefix}}-{{language}}.json. | 42 | | staticFolder | Optional | `static` | Specify folder in static 43 | 44 | ## Migration from v1 to v2 45 | 46 | Dynamic i18n has been updated to work with the new version of [https://theoephraim.github.io/node-google-spreadsheet/#/](google-spreadsheet) and the `title` option to locate the tab has been replaced by `id` which is the `gid` identifier that you can get from the google sheet url query params `gid`. 47 | 48 | ## 📑 License 49 | 50 | [MIT License](./LICENSE) - Nuxt Community 51 | -------------------------------------------------------------------------------- /providers/google-sheet-provider.js: -------------------------------------------------------------------------------- 1 | const _ = require('lodash') 2 | const fs = require('fs') 3 | const path = require('path') 4 | 5 | const { GoogleSpreadsheet } = require('google-spreadsheet') 6 | const KEYS = 'KEYS' 7 | const VARS = 'VARS' 8 | 9 | function cb(fn, ...args) { 10 | return new Promise((resolve, reject) => { 11 | fn(...args, (err, result) => { 12 | if (err) return reject(err) 13 | resolve(result) 14 | }) 15 | }) 16 | } 17 | 18 | function checkExportConfigurationFile(conf) { 19 | const fields = ['providerKey', 'credentials'] 20 | 21 | return _.every(fields, _.partial(_.has, conf)) 22 | } 23 | 24 | function formatCell(cell) { 25 | if (!cell) return '' 26 | 27 | return cell.replace(/(\r\n|\n|\r)/gm, "", '').replace(/ /g, '').split(',') 28 | } 29 | 30 | async function extract({ rows, path, conf }) { 31 | var i18n = {} 32 | 33 | _.forEach(conf.languages, (language) => { 34 | i18n[language] = {} 35 | }) 36 | 37 | _.each(rows, (row) => { 38 | const keys = formatCell(row[KEYS]) 39 | const variables = formatCell(row[VARS]) 40 | 41 | if (keys.length > 0) { 42 | _.forEach(conf.languages, (language) => { 43 | if (_.has(row, language.toUpperCase())) { 44 | const value = row[language.toUpperCase()].replace(/ +/g, ' ') 45 | 46 | assignValue(i18n, language, keys, variables, value) 47 | } 48 | }) 49 | } 50 | }) 51 | 52 | if (!path) return i18n 53 | 54 | return save(i18n, path, conf) 55 | } 56 | 57 | async function save(i18n, directory, conf) { 58 | if (!fs.existsSync(directory)) { 59 | fs.mkdirSync(directory) 60 | } 61 | 62 | _.forEach(conf.languages, (language) => { 63 | const filePath = path.join(directory, `${conf.outputFilePrefix}-${language}.json`) 64 | const jsonData = JSON.stringify(i18n[language], null, 4) 65 | 66 | try { 67 | fs.writeFileSync(filePath, jsonData) 68 | } catch (err) { 69 | return Promise.reject(err) 70 | } 71 | }) 72 | 73 | return i18n 74 | } 75 | 76 | function assignValue(i18n, language, keys, variables, value) { 77 | _.each(keys, (key) => { 78 | if (!_.isEmpty(key)) { 79 | const tree = key.split('.') 80 | const object = getObjectFromTree(i18n[language], tree.slice(0, tree.length - 1)) 81 | const val = parseValue(value, variables) 82 | if (!_.isEmpty(val)) { 83 | object[tree[tree.length - 1]] = val 84 | } 85 | } 86 | }) 87 | } 88 | 89 | function parseValue(value, variables) { 90 | if (_.isEmpty(variables)) return value 91 | 92 | var parsed = value 93 | _.each(variables, function (variable, index) { 94 | if (!_.isEmpty(variable)) { 95 | parsed = parsed.replace(new RegExp('\\[' + (index + 1) + '\\]', 'g'), '{{' + variable + '}}') 96 | } 97 | }) 98 | 99 | return parsed 100 | } 101 | 102 | function getObjectFromTree(object, tree) { 103 | const key = tree.splice(0, 1)[0] 104 | if (!object[key]) object[key] = {} 105 | 106 | return (tree.length > 0) ? getObjectFromTree(object[key], tree) : object[key] 107 | } 108 | 109 | async function importI18n({ path, conf, log }) { 110 | if (!checkExportConfigurationFile(conf)) return Promise.reject('Bad configuration file') 111 | 112 | const doc = new GoogleSpreadsheet(conf['providerKey']) 113 | 114 | await doc.useServiceAccountAuth(conf.credentials) 115 | await doc.loadInfo() 116 | 117 | // If no gid provided we load the first tab 118 | const worksheet = conf.id ? doc.sheetsById[conf.id] : doc.sheetsByIndex[0] 119 | 120 | if (!worksheet) return Promise.reject(`Unable to find ${conf.id} worksheet tab`) 121 | 122 | const rows = await worksheet.getRows() 123 | const i18n = await extract({ rows, path, conf, log }) 124 | 125 | log(`Extract: ${rows.length} rows`) 126 | 127 | return i18n 128 | } 129 | 130 | module.exports = { 131 | importI18n 132 | } 133 | -------------------------------------------------------------------------------- /yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | abort-controller@^3.0.0: 6 | version "3.0.0" 7 | resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392" 8 | integrity sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg== 9 | dependencies: 10 | event-target-shim "^5.0.0" 11 | 12 | agent-base@6: 13 | version "6.0.0" 14 | resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.0.tgz#5d0101f19bbfaed39980b22ae866de153b93f09a" 15 | integrity sha512-j1Q7cSCqN+AwrmDd+pzgqc0/NpC655x2bUf5ZjRIO77DcNBFmh+OgRNzF6OKdCC9RSCb19fGd99+bhXFdkRNqw== 16 | dependencies: 17 | debug "4" 18 | 19 | arrify@^2.0.0: 20 | version "2.0.1" 21 | resolved "https://registry.yarnpkg.com/arrify/-/arrify-2.0.1.tgz#c9655e9331e0abcd588d2a7cad7e9956f66701fa" 22 | integrity sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug== 23 | 24 | axios@^0.19.1: 25 | version "0.19.2" 26 | resolved "https://registry.yarnpkg.com/axios/-/axios-0.19.2.tgz#3ea36c5d8818d0d5f8a8a97a6d36b86cdc00cb27" 27 | integrity sha512-fjgm5MvRHLhx+osE2xoekY70AhARk3a6hkN+3Io1jc00jtquGvxYlKlsFUhmUET0V5te6CcZI7lcv2Ym61mjHA== 28 | dependencies: 29 | follow-redirects "1.5.10" 30 | 31 | base64-js@^1.3.0: 32 | version "1.3.1" 33 | resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.3.1.tgz#58ece8cb75dd07e71ed08c736abc5fac4dbf8df1" 34 | integrity sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g== 35 | 36 | bignumber.js@^7.0.0: 37 | version "7.2.1" 38 | resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-7.2.1.tgz#80c048759d826800807c4bfd521e50edbba57a5f" 39 | integrity sha512-S4XzBk5sMB+Rcb/LNcpzXr57VRTxgAvaAEDAl1AwRx27j00hT84O6OkteE7u8UB3NuaaygCRrEpqox4uDOrbdQ== 40 | 41 | buffer-equal-constant-time@1.0.1: 42 | version "1.0.1" 43 | resolved "https://registry.yarnpkg.com/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz#f8e71132f7ffe6e01a5c9697a4c6f3e48d5cc819" 44 | integrity sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk= 45 | 46 | debug@4: 47 | version "4.1.1" 48 | resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791" 49 | integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw== 50 | dependencies: 51 | ms "^2.1.1" 52 | 53 | debug@=3.1.0: 54 | version "3.1.0" 55 | resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" 56 | integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g== 57 | dependencies: 58 | ms "2.0.0" 59 | 60 | ecdsa-sig-formatter@1.0.11, ecdsa-sig-formatter@^1.0.11: 61 | version "1.0.11" 62 | resolved "https://registry.yarnpkg.com/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz#ae0f0fa2d85045ef14a817daa3ce9acd0489e5bf" 63 | integrity sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ== 64 | dependencies: 65 | safe-buffer "^5.0.1" 66 | 67 | event-target-shim@^5.0.0: 68 | version "5.0.1" 69 | resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789" 70 | integrity sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ== 71 | 72 | extend@^3.0.2: 73 | version "3.0.2" 74 | resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" 75 | integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== 76 | 77 | fast-text-encoding@^1.0.0: 78 | version "1.0.1" 79 | resolved "https://registry.yarnpkg.com/fast-text-encoding/-/fast-text-encoding-1.0.1.tgz#4a428566f74fc55ebdd447555b1eb4d9cf514455" 80 | integrity sha512-x4FEgaz3zNRtJfLFqJmHWxkMDDvXVtaznj2V9jiP8ACUJrUgist4bP9FmDL2Vew2Y9mEQI/tG4GqabaitYp9CQ== 81 | 82 | follow-redirects@1.5.10: 83 | version "1.5.10" 84 | resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.5.10.tgz#7b7a9f9aea2fdff36786a94ff643ed07f4ff5e2a" 85 | integrity sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ== 86 | dependencies: 87 | debug "=3.1.0" 88 | 89 | gaxios@^2.1.0: 90 | version "2.3.2" 91 | resolved "https://registry.yarnpkg.com/gaxios/-/gaxios-2.3.2.tgz#ed666826c2039b89d384907cc075595269826553" 92 | integrity sha512-K/+py7UvKRDaEwEKlLiRKrFr+wjGjsMz5qH7Vs549QJS7cpSCOT/BbWL7pzqECflc46FcNPipjSfB+V1m8PAhw== 93 | dependencies: 94 | abort-controller "^3.0.0" 95 | extend "^3.0.2" 96 | https-proxy-agent "^5.0.0" 97 | is-stream "^2.0.0" 98 | node-fetch "^2.3.0" 99 | 100 | gcp-metadata@^3.4.0: 101 | version "3.5.0" 102 | resolved "https://registry.yarnpkg.com/gcp-metadata/-/gcp-metadata-3.5.0.tgz#6d28343f65a6bbf8449886a0c0e4a71c77577055" 103 | integrity sha512-ZQf+DLZ5aKcRpLzYUyBS3yo3N0JSa82lNDO8rj3nMSlovLcz2riKFBsYgDzeXcv75oo5eqB2lx+B14UvPoCRnA== 104 | dependencies: 105 | gaxios "^2.1.0" 106 | json-bigint "^0.3.0" 107 | 108 | google-auth-library@^5.9.1: 109 | version "5.10.1" 110 | resolved "https://registry.yarnpkg.com/google-auth-library/-/google-auth-library-5.10.1.tgz#504ec75487ad140e68dd577c21affa363c87ddff" 111 | integrity sha512-rOlaok5vlpV9rSiUu5EpR0vVpc+PhN62oF4RyX/6++DG1VsaulAFEMlDYBLjJDDPI6OcNOCGAKy9UVB/3NIDXg== 112 | dependencies: 113 | arrify "^2.0.0" 114 | base64-js "^1.3.0" 115 | ecdsa-sig-formatter "^1.0.11" 116 | fast-text-encoding "^1.0.0" 117 | gaxios "^2.1.0" 118 | gcp-metadata "^3.4.0" 119 | gtoken "^4.1.0" 120 | jws "^4.0.0" 121 | lru-cache "^5.0.0" 122 | 123 | google-p12-pem@^2.0.0: 124 | version "2.0.4" 125 | resolved "https://registry.yarnpkg.com/google-p12-pem/-/google-p12-pem-2.0.4.tgz#036462394e266472632a78b685f0cc3df4ef337b" 126 | integrity sha512-S4blHBQWZRnEW44OcR7TL9WR+QCqByRvhNDZ/uuQfpxywfupikf/miba8js1jZi6ZOGv5slgSuoshCWh6EMDzg== 127 | dependencies: 128 | node-forge "^0.9.0" 129 | 130 | google-spreadsheet@^4.0.0: 131 | version "3.0.10" 132 | resolved "https://registry.yarnpkg.com/google-spreadsheet/-/google-spreadsheet-3.0.10.tgz#3aac6fd2a766a3943a27f09fbb45ed501e54ddcd" 133 | integrity sha512-FQNaXAUzE+W9AE3Sd3O9BMPnC4x1FZSjBt+X8G+s9x14nJ/xk0waIJiou44q+E0WKr9fi12UANEwVRAd5vvDEw== 134 | dependencies: 135 | axios "^0.19.1" 136 | google-auth-library "^5.9.1" 137 | lodash "^4.17.15" 138 | 139 | gtoken@^4.1.0: 140 | version "4.1.4" 141 | resolved "https://registry.yarnpkg.com/gtoken/-/gtoken-4.1.4.tgz#925ff1e7df3aaada06611d30ea2d2abf60fcd6a7" 142 | integrity sha512-VxirzD0SWoFUo5p8RDP8Jt2AGyOmyYcT/pOUgDKJCK+iSw0TMqwrVfY37RXTNmoKwrzmDHSk0GMT9FsgVmnVSA== 143 | dependencies: 144 | gaxios "^2.1.0" 145 | google-p12-pem "^2.0.0" 146 | jws "^4.0.0" 147 | mime "^2.2.0" 148 | 149 | https-proxy-agent@^5.0.0: 150 | version "5.0.0" 151 | resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz#e2a90542abb68a762e0a0850f6c9edadfd8506b2" 152 | integrity sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA== 153 | dependencies: 154 | agent-base "6" 155 | debug "4" 156 | 157 | is-stream@^2.0.0: 158 | version "2.0.0" 159 | resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.0.tgz#bde9c32680d6fae04129d6ac9d921ce7815f78e3" 160 | integrity sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw== 161 | 162 | json-bigint@^0.3.0: 163 | version "0.3.0" 164 | resolved "https://registry.yarnpkg.com/json-bigint/-/json-bigint-0.3.0.tgz#0ccd912c4b8270d05f056fbd13814b53d3825b1e" 165 | integrity sha1-DM2RLEuCcNBfBW+9E4FLU9OCWx4= 166 | dependencies: 167 | bignumber.js "^7.0.0" 168 | 169 | jwa@^2.0.0: 170 | version "2.0.0" 171 | resolved "https://registry.yarnpkg.com/jwa/-/jwa-2.0.0.tgz#a7e9c3f29dae94027ebcaf49975c9345593410fc" 172 | integrity sha512-jrZ2Qx916EA+fq9cEAeCROWPTfCwi1IVHqT2tapuqLEVVDKFDENFw1oL+MwrTvH6msKxsd1YTDVw6uKEcsrLEA== 173 | dependencies: 174 | buffer-equal-constant-time "1.0.1" 175 | ecdsa-sig-formatter "1.0.11" 176 | safe-buffer "^5.0.1" 177 | 178 | jws@^4.0.0: 179 | version "4.0.0" 180 | resolved "https://registry.yarnpkg.com/jws/-/jws-4.0.0.tgz#2d4e8cf6a318ffaa12615e9dec7e86e6c97310f4" 181 | integrity sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg== 182 | dependencies: 183 | jwa "^2.0.0" 184 | safe-buffer "^5.0.1" 185 | 186 | lodash@^4.17.15, lodash@^4.17.5: 187 | version "4.17.15" 188 | resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" 189 | integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== 190 | 191 | lru-cache@^5.0.0: 192 | version "5.1.1" 193 | resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" 194 | integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w== 195 | dependencies: 196 | yallist "^3.0.2" 197 | 198 | mime@^2.2.0: 199 | version "2.4.4" 200 | resolved "https://registry.yarnpkg.com/mime/-/mime-2.4.4.tgz#bd7b91135fc6b01cde3e9bae33d659b63d8857e5" 201 | integrity sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA== 202 | 203 | ms@2.0.0: 204 | version "2.0.0" 205 | resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" 206 | integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= 207 | 208 | ms@^2.1.1: 209 | version "2.1.2" 210 | resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" 211 | integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== 212 | 213 | node-fetch@^2.3.0: 214 | version "2.6.0" 215 | resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.0.tgz#e633456386d4aa55863f676a7ab0daa8fdecb0fd" 216 | integrity sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA== 217 | 218 | node-forge@^0.9.0: 219 | version "0.9.1" 220 | resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.9.1.tgz#775368e6846558ab6676858a4d8c6e8d16c677b5" 221 | integrity sha512-G6RlQt5Sb4GMBzXvhfkeFmbqR6MzhtnT7VTHuLadjkii3rdYHNdw0m8zA4BTxVIh68FicCQ2NSUANpsqkr9jvQ== 222 | 223 | safe-buffer@^5.0.1: 224 | version "5.2.0" 225 | resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.0.tgz#b74daec49b1148f88c64b68d49b1e815c1f2f519" 226 | integrity sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg== 227 | 228 | vue-i18n@^7.6.0: 229 | version "7.8.1" 230 | resolved "https://registry.yarnpkg.com/vue-i18n/-/vue-i18n-7.8.1.tgz#2ce4b6efde679a1e05ddb5d907bfc1bc218803b2" 231 | integrity sha512-BzB+EAPo/iFyFn/GXd/qVdDe67jfk+gmQaWUKD5BANhUclGrFxzRExzW2pYEAbhNm2pg0F12Oo+gL2IMLDcTAw== 232 | 233 | yallist@^3.0.2: 234 | version "3.1.1" 235 | resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" 236 | integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== 237 | --------------------------------------------------------------------------------