Skip to content

Commit

Permalink
feat: pickup from unplugin-vue-i18n plugin options to nuxt i18n optio…
Browse files Browse the repository at this point in the history
…ns (#2323)
  • Loading branch information
kazupon authored Aug 17, 2023
1 parent 4c62a36 commit fdf54f4
Show file tree
Hide file tree
Showing 10 changed files with 102 additions and 46 deletions.
41 changes: 26 additions & 15 deletions docs/content/3.options/6.misc.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,7 @@ Miscellaneous options.
Configure the flag for experimental features of the nuxt i18n module.

::alert{type="info"}

This module option setting is also set to the runtime config.

::

Supported properties:
Expand All @@ -25,22 +23,28 @@ Supported properties:
## `bundle`

- type: `object`
- default: `{ compositionOnly: true }`
- default: `{ compositionOnly: true, runtimeOnly: false, fullInstall: true }`

Configure the bundling optimization for nuxt i18n module.

Supported properties:

- `compositionOnly` (default: `true`) - Whether to make vue-i18n API only composition API. By default the legacy API is tree-shaken. For more details, See [here](https://vue-i18n.intlify.dev/guide/advanced/optimization.html#reduce-bundle-size-with-feature-build-flags)
- `compositionOnly` (default: `true`) - Whether to make vue-i18n API only composition API. By default the legacy API is tree-shaken. For more details, See [here](https://vue-i18n.intlify.dev/guide/advanced/optimization.html#reduce-bundle-size-with-feature-build-flags)

::alert{type="warning"}

If you would like to use Vue I18n's Legacy API, you must set `compositionOnly: false`. **Note that setting this value will disable Vue I18n Composition API**.

Note that the Legacy API can also be used in hybrid by setting the Vue I18n option to `allowComposition: true` in i18n.config, but this is limited. See [here](https://vue-i18n.intlify.dev/guide/migration/vue3.html) for details.
::

- `runtimeOnly` (default: `false`)a - Whether or not to automatically use Vue I18n runtime-only in build.

::alert{type="warning"}
When you will enable this option, vue-i18n message compiler is not bundled. This means that you will not be able to dynamically retrieve locale messages for use in your application from back-end APIs or DB via fetch, or programmatically compose the locale messages. That is to say, **you must be able to fully resolve locale messages at build time.**
::

- `fullInstall` (default: `true`) - Whether to install the full set of APIs, components, etc. By default, all of them will be installed. If `false` is specified, buld-in components (`i18n-t`, `i18n-d` and `i18n-n`) and directive (`v-t`) will not be installed in vue and will be tree-shaken. For more details, See [here](https://vue-i18n.intlify.dev/guide/advanced/optimization.html#reduce-bundle-size-with-feature-build-flags)


## `compilation`

Expand All @@ -54,27 +58,38 @@ Supported properties:
- `jit` (default: `true`) Whether to use the JIT compilation of Vue I18n message compiler.

::alert{type="warning"}

Mean that necessary to pre-compile locale messages that are not managed by the nuxt i18n module (e.g. in the case of importing from a specific URL, you will need to precompile them yourself.)

And also, you need to understand that you cannot support use cases where you dynamically compose locale messages from the back-end via an API.

::

- `strictMessage` (default: `true`) Strictly check that the locale message does not contain HTML tags. If HTML tags are included, an error is thrown.
::alert{type="warning"}

::alert{type="warning"}
If you do not want the error to be thrown, you can work around it by setting it to false. However, **this means that the locale message might cause security issues with XSS**. In that case, we recommend setting the `escapeHtml` option to `true`.

::

- `escapeHtml` (default: `false`) - Determine whether to escape HTML tags if they are included in the locale message.
::alert{type="warning"}

::alert{type="warning"}
If `strictMessage` is disabled by setting it to `false`, we recommend enabling this option.

::


## `customBlocks`

- type: `object`
- default: `{ defaultSFCLang: 'json', globalSFCScope: false }`

Configure the `i18n` custom blocks of SFC.

Supported properties:

- `defaultSFCLang` (default: `'json'`) - Specify the content for all your inlined i18n custom blocks on your SFC. about details, see [here](https://github.com/intlify/bundle-tools/blob/main/packages/unplugin-vue-i18n/README.md#defaultsfclang)

- `globalSFCScope` (default: `false`) - Whether to include all `i18n` custom blocks on your SFC on global scope. about details, see [here](https://github.com/intlify/bundle-tools/blob/main/packages/unplugin-vue-i18n/README.md#globalsfcscope)


## `types`

- type: `string` (`composition` or `legacy`)
Expand All @@ -83,9 +98,7 @@ Supported properties:
Enforces the type definition of the API style to be used. if you set `compostion`, Composition API types provided by Vue I18n and `@nuxtjs/i18n` are supported, else `legacy`, Options API types are supported. If you are running a dev server with `nuxi dev`, watching the Nuxt configuration will switch the type.

::alert{type="warning"}

If it can not detect Nuxt configuration changing, you need to run `nuxi prepare`.

::


Expand All @@ -97,11 +110,9 @@ If it can not detect Nuxt configuration changing, you need to run `nuxi prepare`
Whether to use `@nuxtjs/i18n` debug mode. If `true`, logs will be output to the console.

::alert{type="warning"}

The purpose of this option is to help identify any problems with @nuxtjs/i18n.

Don't enable this option for use in production. Performance will be decreased.

::

## `parallelPlugin`
Expand Down
3 changes: 3 additions & 0 deletions playground/nuxt.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,9 @@ export default defineNuxtConfig({
name: 'Français'
}
],
// bundle: {
// runtimeOnly: true
// },
// trailingSlash: true,
debug: true,
defaultLocale: 'en',
Expand Down
1 change: 1 addition & 0 deletions playground/pages/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ definePageMeta({
<div v-for="item in items">
<p>{{ item }}</p>
</div>
<div>v-t directive: <code v-t="{ path: 'hello', args: { name: 'v-t' } }"></code></div>
</div>
</template>

Expand Down
15 changes: 11 additions & 4 deletions src/alias.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,16 @@ import { tryResolve, getLayerRootDirs, getPackageManagerType } from './utils'

import type { Nuxt } from '@nuxt/schema'
import type { PackageManager } from './utils'
import type { NuxtI18nOptions } from './types'

const debug = createDebug('@nuxtjs/i18n:alias')

export async function setupAlias(nuxt: Nuxt) {
export async function setupAlias(nuxt: Nuxt, options: NuxtI18nOptions) {
const pkgMgr = await getPackageManagerType()
debug('setupAlias: pkgMgr', pkgMgr)

// resolve vue-i18@v9
nuxt.options.alias[VUE_I18N_PKG] = await resolveVueI18nAlias(pkgModulesDir, nuxt, pkgMgr)
nuxt.options.alias[VUE_I18N_PKG] = await resolveVueI18nAlias(pkgModulesDir, options, nuxt, pkgMgr)
nuxt.options.build.transpile.push(VUE_I18N_PKG)
debug('vue-i18n alias', nuxt.options.alias[VUE_I18N_PKG])

Expand Down Expand Up @@ -62,12 +63,18 @@ export async function setupAlias(nuxt: Nuxt) {
* - `@intlify/vue-router-bridge`
*/

export async function resolveVueI18nAlias(pkgModulesDir: string, nuxt: Nuxt, pkgMgr: PackageManager) {
export async function resolveVueI18nAlias(
pkgModulesDir: string,
options: NuxtI18nOptions,
nuxt: Nuxt,
pkgMgr: PackageManager
) {
const { rootDir, workspaceDir } = nuxt.options
const runtimeOnly = options.bundle?.runtimeOnly
const modulePath =
nuxt.options.dev || nuxt.options._prepare
? `${VUE_I18N_PKG}/dist/vue-i18n.mjs`
: `${VUE_I18N_PKG}/dist/vue-i18n.runtime.mjs`
: `${VUE_I18N_PKG}/dist/vue-i18n${runtimeOnly ? '.runtime' : ''}.mjs`
const targets = [
// for Nuxt layer
...getLayerRootDirs(nuxt).map(root => resolve(root, 'node_modules', modulePath)),
Expand Down
27 changes: 19 additions & 8 deletions src/bundler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,9 @@ export async function extendBundler(
const webpack = await import('webpack').then(m => m.default || m)

const webpackPluginOptions: PluginOptions = {
runtimeOnly: true,
allowDynamic: true,
runtimeOnly: nuxtOptions.bundle.runtimeOnly,
compositionOnly: nuxtOptions.bundle.compositionOnly,
jitCompilation: nuxtOptions.compilation.jit,
strictMessage: nuxtOptions.compilation.strictMessage,
escapeHtml: nuxtOptions.compilation.escapeHtml
Expand All @@ -66,9 +67,16 @@ export async function extendBundler(
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- `config.plugins` is safe, so it's assigned with nuxt!
config.plugins!.push(
new webpack.DefinePlugin(
assign(getFeatureFlags(nuxtOptions.compilation.jit, nuxtOptions.bundle.compositionOnly), {
__DEBUG__: String(nuxtOptions.debug)
})
assign(
getFeatureFlags({
jit: nuxtOptions.compilation.jit,
compositionOnly: nuxtOptions.bundle.compositionOnly,
fullInstall: nuxtOptions.bundle.fullInstall
}),
{
__DEBUG__: String(nuxtOptions.debug)
}
)
)
)
})
Expand All @@ -81,12 +89,15 @@ export async function extendBundler(
*/

const vitePluginOptions: PluginOptions = {
runtimeOnly: true,
allowDynamic: true,
runtimeOnly: nuxtOptions.bundle.runtimeOnly,
compositionOnly: nuxtOptions.bundle.compositionOnly,
fullInstall: nuxtOptions.bundle.fullInstall,
jitCompilation: nuxtOptions.compilation.jit,
strictMessage: nuxtOptions.compilation.strictMessage,
escapeHtml: nuxtOptions.compilation.escapeHtml
escapeHtml: nuxtOptions.compilation.escapeHtml,
defaultSFCLang: nuxtOptions.customBlocks.defaultSFCLang,
globalSFCScope: nuxtOptions.customBlocks.globalSFCScope
}
if (hasLocaleFiles && localePaths.length > 0) {
vitePluginOptions.include = localePaths.map(x => resolve(x, './**'))
Expand All @@ -108,9 +119,9 @@ export async function extendBundler(
})
}

export function getFeatureFlags(jit = true, compositionOnly = true) {
export function getFeatureFlags({ jit = true, compositionOnly = true, fullInstall = true }) {
return {
__VUE_I18N_FULL_INSTALL__: 'true',
__VUE_I18N_FULL_INSTALL__: String(fullInstall),
__VUE_I18N_LEGACY_API__: String(!compositionOnly),
__INTLIFY_PROD_DEVTOOLS__: 'false',
__INTLIFY_JIT_COMPILATION__: String(jit)
Expand Down
8 changes: 7 additions & 1 deletion src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,19 @@ export const DEFAULT_OPTIONS = {
jsTsFormatResource: false
},
bundle: {
compositionOnly: true
compositionOnly: true,
runtimeOnly: false,
fullInstall: true
},
compilation: {
jit: true,
strictMessage: true,
escapeHtml: false
},
customBlocks: {
defaultSFCLang: 'json',
globalSFCScope: false
},
vueI18n: '',
locales: [] as string[],
defaultLocale: '',
Expand Down
36 changes: 23 additions & 13 deletions src/module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,25 +100,35 @@ export default defineNuxtModule<NuxtI18nOptions>({
if (options.bundle.compositionOnly && options.types === 'legacy') {
throw new Error(
formatMessage(
`'i18n.bundle.compositionOnly' option and 'i18n.types' option is conflicting: i18n.bundle.compositionOnly: ${
options.bundle.compositionOnly
}, i18n.types: ${JSON.stringify(options.types)}`
'`bundle.compositionOnly` option and `types` option is conflicting: ' +
`bundle.compositionOnly: ${options.bundle.compositionOnly}, types: ${JSON.stringify(options.types)}`
)
)
}

applyLayerOptions(options, nuxt)
await mergeI18nModules(options, nuxt)
if (options.bundle.runtimeOnly && options.compilation.jit) {
logger.warn(
'`bundle.runtimeOnly` option and `compilation.jit` option is conflicting: ' +
`bundle.runtimeOnly: ${options.bundle.runtimeOnly}, compilation.jit: ${JSON.stringify(
options.compilation.jit
)}`
)
}

if (options.strategy === 'no_prefix' && options.differentDomains) {
console.warn(
formatMessage(
'The `differentDomains` option and `no_prefix` strategy are not compatible. ' +
'Change strategy or disable `differentDomains` option.'
)
logger.warn(
'`differentDomains` option and `no_prefix` strategy are not compatible. ' +
'Change strategy or disable `differentDomains` option.'
)
}

/**
* nuxt layers handling ...
*/

applyLayerOptions(options, nuxt)
await mergeI18nModules(options, nuxt)

/**
* setup runtime config
*/
Expand Down Expand Up @@ -161,7 +171,7 @@ export default defineNuxtModule<NuxtI18nOptions>({

const vueI18nConfigPathInfo = await resolveVueI18nConfigInfo(options, nuxt.options.buildDir, nuxt.options.rootDir)
if (vueI18nConfigPathInfo.absolute == null) {
logger.warn(`Vue I18n configuration file does not exist at ${vueI18nConfigPathInfo.relative}. Skipping...`)
logger.info(`Vue I18n configuration file does not exist at ${vueI18nConfigPathInfo.relative}. Skipping...`)
}
debug('vueI18nConfigPathInfo', vueI18nConfigPathInfo)

Expand All @@ -187,7 +197,7 @@ export default defineNuxtModule<NuxtI18nOptions>({
* setup module alias
*/

await setupAlias(nuxt)
await setupAlias(nuxt, options)

/**
* add plugin and templates
Expand Down Expand Up @@ -288,7 +298,7 @@ export default defineNuxtModule<NuxtI18nOptions>({
*/

const pkgMgr = await getPackageManagerType()
const vueI18nPath = await resolveVueI18nAlias(pkgModulesDir, nuxt, pkgMgr)
const vueI18nPath = await resolveVueI18nAlias(pkgModulesDir, options, nuxt, pkgMgr)
debug('vueI18nPath for auto-import', vueI18nPath)

await addComponent({
Expand Down
6 changes: 5 additions & 1 deletion src/nitro.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,11 @@ export async function setupNitro(nuxt: Nuxt, nuxtOptions: Required<NuxtI18nOptio
// vue-i18n feature flags configuration for server-side (server api, server middleware, etc...)
nitroConfig.replace = assign(
nitroConfig.replace || {},
getFeatureFlags(nuxtOptions.compilation.jit, nuxtOptions.bundle.compositionOnly)
getFeatureFlags({
jit: nuxtOptions.compilation.jit,
compositionOnly: nuxtOptions.bundle.compositionOnly,
fullInstall: nuxtOptions.bundle.fullInstall
})
)

// setup debug flag
Expand Down
5 changes: 4 additions & 1 deletion src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,9 @@ export interface ExperimentalFeatures {
jsTsFormatResource?: boolean
}

export interface BundleOptions extends Pick<PluginOptions, 'compositionOnly'> {}
export interface BundleOptions extends Pick<PluginOptions, 'compositionOnly' | 'runtimeOnly' | 'fullInstall'> {}

export interface CustomBlocksOptions extends Pick<PluginOptions, 'defaultSFCLang' | 'globalSFCScope'> {}

export interface LocaleMessageCompilationOptions {
jit?: boolean
Expand All @@ -75,6 +77,7 @@ export type NuxtI18nOptions<Context = unknown> = {
experimental?: ExperimentalFeatures
bundle?: BundleOptions
compilation?: LocaleMessageCompilationOptions
customBlocks?: CustomBlocksOptions
differentDomains?: boolean
detectBrowserLanguage?: DetectBrowserLanguageOptions | false
langDir?: string | null
Expand Down
Loading

0 comments on commit fdf54f4

Please sign in to comment.