Skip to content
This repository was archived by the owner on Jul 4, 2021. It is now read-only.

Commit

Permalink
feat: add default lang and global scope plugin options for SFC i18n
Browse files Browse the repository at this point in the history
… custom block (#109)

* feat: add `defaultSFCLang` and `globalSFCScope` configuration options

* chore: exclude intellij/webstorm stuff from `.gitignore`

* chore: add logic to use new configuration options only on SFC custom blocks

* chore: remove extra comma

* chore: add `defaultSFCLang` and `globalSFCScope` options on `test/utils.ts` on build function

* test: add `defaultSFCLang` and `globalSFCScope` tests on custom blocks
test: add `default-lang.vue` for `defaultSFCLang` and `globalSFCScope` tests

* test: add `defaultSFCLang` and `globalSFCScope` snapshots tests

* test: add `globalSFCScope and import` test

* test: add `globalSFCScope and import` snapshot test

* docs: correct some small errata and wording
docs: add docs for `defaultSFCLang` and `globalSFCScope`

* docs: add hint for `defaultSFCLang` and warning for `globalSFCScope`
  • Loading branch information
userquin authored Jul 1, 2021
1 parent cd1ba32 commit 8ee092b
Show file tree
Hide file tree
Showing 9 changed files with 191 additions and 7 deletions.
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,6 @@ lib
*.swp
*~
examples/**/dist
.env
.env
# intellij/webstorm stuff
.idea/
91 changes: 87 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ Also, if you do a production build with vite, Vue I18n will automatically bundle

### i18n resources pre-compilation

Since [email protected], The locale messages are handled with message compiler, which converts them to javascript functions after compiling. After compiling, message compiler converts them into javascript functions, which can improve the performance of the application.
Since [email protected], the locale messages are handled with message compiler, which converts them to javascript functions after compiling. After compiling, message compiler converts them into javascript functions, which can improve the performance of the application.

However, with the message compiler, the javascript function conversion will not work in some environments (e.g. CSP). For this reason, [email protected] and later offer a full version that includes compiler and runtime, and a runtime only version.

Expand Down Expand Up @@ -122,7 +122,7 @@ export default defineConfig({

### i18n custom block

the below example that `examples/composition/App.vue` have i18n custom block:
The below example that `examples/composition/App.vue` have `i18n` custom block:

```vue
<template>
Expand Down Expand Up @@ -171,9 +171,10 @@ You can be used by specifying the following format in the `lang` attribute:

- json (default)
- yaml
- yml
- json5

example `yaml` foramt:
example `yaml` format:

```vue
<i18n lang="yaml">
Expand Down Expand Up @@ -322,7 +323,7 @@ About details, See the below section

Whether pre-compile number and boolean values as message functions that return the string value.

for example, the following json resources:
For example, the following json resources:

```json
{
Expand Down Expand Up @@ -372,6 +373,88 @@ About details, See the below section
}
```

### `defaultSFCLang`

- **Type:** `string`
- **Default:** `undefined`

Specify the content for all your inlined `i18n` custom blocks on your `SFC`.

`defaultSFCLang` must have one of the following values:

```
- json
- json5
- yaml
- yml
```

On inlined `i18n` custom blocks that have specified the `lang` attribute, the `defaultSFCLang` is not applied.

For example, with `defaultSFCLang: "yaml"` or `defaultSFCLang: "yml"`, this custom block:
```html
<i18n lang="yaml">
en:
hello: Hello
es:
hello: Hola
</i18n>
```

and this another one, are equivalent:
```html
<i18n>
en:
hello: Hello
es:
hello: Hola
</i18n>
```

### `globalSFCScope`

- **Type:** `boolean`
- **Default:** `undefined`

Whether to include all `i18n` custom blocks on your `SFC` on `global` scope.

If `true`, it will be applied to all inlined `i18n` or `imported` custom blocks.

**Warning**: beware enabling `globalSFCScope: true`, all `i18n` custom blocks in all your `SFC` will be on `global` scope.

For example, with `globalSFCScope: true`, this custom block:

```html
<i18n lang="yaml" global>
en:
hello: Hello
es:
hello: Hola
</i18n>
```

and this another one, are equivalent:

```html
<i18n lang="yaml">
en:
hello: Hello
es:
hello: Hola
</i18n>
```

You can also use `defaultSFCLang: "yaml"`, following with previous example, this another is also equivalent to previous ones:

```html
<i18n>
en:
hello: Hello
es:
hello: Hola
</i18n>
```

## :scroll: Changelog

Details changes for each release are documented in the [CHANGELOG.md](https://github.com/intlify/vite-plugin-vue-i18n/blob/master/CHANGELOG.md).
Expand Down
13 changes: 13 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,12 @@ function pluginI18n(
const fullIinstall = isBoolean(options.fullInstall)
? options.fullInstall
: true
const defaultSFCLang = isString(options.defaultSFCLang)
? options.defaultSFCLang
: undefined
const globalSFCScope = isBoolean(options.globalSFCScope)
? options.globalSFCScope
: false
let config: ResolvedConfig | null = null

return {
Expand Down Expand Up @@ -187,12 +193,19 @@ function pluginI18n(
if ('src' in query) {
if (isString(query.lang)) {
langInfo = query.lang === 'i18n' ? 'json' : query.lang
} else if (defaultSFCLang) {
langInfo = defaultSFCLang
}
} else {
if (isString(query.lang)) {
langInfo = query.lang
} else if (defaultSFCLang) {
langInfo = defaultSFCLang
}
}
if (!parseOptions.isGlobal && globalSFCScope) {
parseOptions.isGlobal = true
}
const generate = /\.?json5?/.test(langInfo)
? generateJSON
: generateYAML
Expand Down
2 changes: 2 additions & 0 deletions src/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,6 @@ export type VitePluginVueI18nOptions = {
compositionOnly?: boolean
fullInstall?: boolean
include?: string | string[]
defaultSFCLang?: 'json' | 'json5' | 'yml' | 'yaml'
globalSFCScope?: boolean
}
39 changes: 39 additions & 0 deletions test/__snapshots__/custom-block.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,32 @@ Array [
]
`;

exports[`default lang 1`] = `
Array [
Object {
"locale": "",
"resource": Object {
"en": Object {
"hello": [Function],
},
},
},
]
`;

exports[`default lang and global scope 1`] = `
Array [
Object {
"locale": "",
"resource": Object {
"en": Object {
"hello": [Function],
},
},
},
]
`;

exports[`global 1`] = `
Array [
Object {
Expand All @@ -37,6 +63,19 @@ Array [
]
`;

exports[`global scope and import 1`] = `
Array [
Object {
"locale": "",
"resource": Object {
"en": Object {
"hello": [Function],
},
},
},
]
`;

exports[`import 1`] = `
Array [
Object {
Expand Down
32 changes: 32 additions & 0 deletions test/custom-block.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,3 +104,35 @@ test('global', async () => {
expect(g.locale).toEqual('')
expect(g.resource.en.hello(createMessageContext())).toEqual('hello global!')
})

test('default lang', async () => {
const { module } = await bundleAndRun('default-lang.vue', {
defaultSFCLang: 'yml'
})
expect(module.__i18n).toMatchSnapshot()
const l = module.__i18n.pop()
expect(l.resource.en.hello(createMessageContext())).toEqual(
'hello from defaults!'
)
})

test('default lang and global scope', async () => {
const { module } = await bundleAndRun('default-lang.vue', {
defaultSFCLang: 'yml',
globalSFCScope: true
})
expect(module.__i18nGlobal).toMatchSnapshot()
const g = module.__i18nGlobal.pop()
expect(g.resource.en.hello(createMessageContext())).toEqual(
'hello from defaults!'
)
})

test('global scope and import', async () => {
const { module } = await bundleAndRun('global-scope-import.vue', {
globalSFCScope: true
})
expect(module.__i18nGlobal).toMatchSnapshot()
const g = module.__i18nGlobal.pop()
expect(g.resource.en.hello(createMessageContext())).toEqual('hello world!')
})
4 changes: 4 additions & 0 deletions test/fixtures/default-lang.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<i18n>
en:
hello: hello from defaults!
</i18n>
2 changes: 2 additions & 0 deletions test/fixtures/global-scope-import.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
<i18n src="./message.json">
</i18n>
11 changes: 9 additions & 2 deletions test/utils.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { isBoolean } from '@intlify/shared'
import { isBoolean, isString } from '@intlify/shared'
import path from 'path'
import { build } from 'vite'
import vue from '@vitejs/plugin-vue'
Expand All @@ -18,6 +18,12 @@ async function bundle(fixture: string, options: Record<string, unknown> = {}) {
? 'info'
: 'silent'
: 'silent'
const defaultSFCLang = isString(options.defaultSFCLang)
? options.defaultSFCLang
: undefined
const globalSFCScope = isBoolean(options.globalSFCScope)
? options.globalSFCScope
: undefined

const alias: Record<string, string> = {
vue: 'vue/dist/vue.runtime.esm-browser.js'
Expand All @@ -26,7 +32,8 @@ async function bundle(fixture: string, options: Record<string, unknown> = {}) {
alias['~target'] = path.resolve(__dirname, target, fixture)
}

const plugins = [vue(), vueI18n({ include })]
// @ts-ignore
const plugins = [vue(), vueI18n({ include, defaultSFCLang, globalSFCScope })]
if (options.intlify) {
const intlifyVue = (await import('../src/injection')).default
plugins.push(intlifyVue(options.intlify as InjectionValues))
Expand Down

0 comments on commit 8ee092b

Please sign in to comment.