Skip to content

Commit

Permalink
feat: add property bundle.onlyLocales (#2478)
Browse files Browse the repository at this point in the history
  • Loading branch information
imslepov committed Oct 12, 2023
1 parent 8a33fec commit 1fc1f02
Show file tree
Hide file tree
Showing 14 changed files with 217 additions and 2 deletions.
13 changes: 13 additions & 0 deletions docs/content/3.options/7.bundle.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,16 @@ If you use this option, you need to enable the `compilation.jit` option.
::alert{type="warning"}
If you enable this option, **you should check resources in your application are pre-compiled with nuxt i18n module**. If you will be loading resources dynamically from the back-end via the API, enabling this option does not work because there is no message compiler.
::

### `onlyLocales`

- type: `string | string[]`
- default: `undefined`

Specify the locales codes that need to be included, the rest will be removed.

It can be useful if you have one code base (e.g. [Nuxt Layers](https://nuxt.com/docs/getting-started/layers)) for several similar projects using different languages.

::alert{type="warning"}
The value of this **option will not be merged with other Nuxt Layers**. This option should only be specified in the final project config.
::
9 changes: 9 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

28 changes: 28 additions & 0 deletions specs/exclude_locales.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { test, expect } from 'vitest'
import { fileURLToPath } from 'node:url'
import { setup, url, createPage } from './utils'
import { getText } from './helper'

await setup({
rootDir: fileURLToPath(new URL(`./fixtures/locale_codes`, import.meta.url)),
browser: true,
// overrides
nuxtConfig: {
i18n: {
bundle: {
onlyLocales: 'en'
}
}
}
})

test('leave only English locale', async () => {
const home = url('/')
const page = await createPage()
await page.goto(home)

const locales = await page.locator('li')

expect(await locales.count()).toEqual(1)
expect(await getText(page, 'li')).toMatch('en')
})
12 changes: 12 additions & 0 deletions specs/fixtures/locale_codes/app.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<script setup lang="ts">
import { useI18n } from '#i18n'
const { locales } = useI18n()
</script>

<template>
<ul>
<li v-for="locale in locales" :key="locale.code">
{{ locale.code }}
</li>
</ul>
</template>
4 changes: 4 additions & 0 deletions specs/fixtures/locale_codes/i18n.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export default {
legacy: false,
fallbackLocale: 'en'
}
9 changes: 9 additions & 0 deletions specs/fixtures/locale_codes/layers/i18n-layer/i18n.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
export default defineI18nConfig(() => {
return {
messages: {
ja: {
layerText: 'これはマージされたロケールキーです'
}
}
}
})
28 changes: 28 additions & 0 deletions specs/fixtures/locale_codes/layers/i18n-layer/nuxt.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// import type { NuxtApp } from 'nuxt/dist/app/index'

// https://nuxt.com/docs/guide/directory-structure/nuxt.config
export default defineNuxtConfig({
modules: ['@nuxtjs/i18n'],
i18n: {
locales: [
{
code: 'en',
iso: 'en-US',
name: 'English'
},
{
code: 'fr',
iso: 'fr-FR',
name: 'Francais'
},
{
code: 'nl',
iso: 'nl-NL',
name: 'Nederlands'
}
],
bundle: {
onlyLocales: ['en', 'fr']
}
}
})
33 changes: 33 additions & 0 deletions specs/fixtures/locale_codes/modules/ExtendI18n.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { defineNuxtModule } from '@nuxt/kit'

export default defineNuxtModule({
async setup(options, nuxt) {
nuxt.hook('i18n:registerModule', register => {
register({
langDir: './lang',
locales: [
{
code: 'en',
iso: 'en-US',
name: 'English'
},
{
code: 'fr',
iso: 'fr-FR',
name: 'Francais'
},
{
code: 'nl',
iso: 'nl-NL',
name: 'Nederlands'
},
{
code: 'ja',
iso: 'ja-JP',
name: 'Japanese'
}
]
})
})
}
})
35 changes: 35 additions & 0 deletions specs/fixtures/locale_codes/nuxt.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// https://nuxt.com/docs/guide/directory-structure/nuxt.config
export default defineNuxtConfig({
modules: ['./modules/ExtendI18n'],

extends: './layers/i18n-layer',

vite: {
build: {
minify: false
}
},

experimental: {
reactivityTransform: true
},

i18n: {
baseUrl: 'http://localhost:3000',
locales: [
{
code: 'en',
iso: 'en',
name: 'English'
},
{
code: 'fr',
iso: 'fr-FR',
name: 'Français'
}
],
defaultLocale: 'en',
skipSettingLocaleOnNavigate: true,
detectBrowserLanguage: false
}
})
15 changes: 15 additions & 0 deletions specs/fixtures/locale_codes/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"name": "nuxt3-test-locale-codes",
"private": true,
"type": "module",
"scripts": {
"build": "nuxi build",
"dev": "nuxi dev",
"generate": "nuxi generate",
"preview": "nuxi preview"
},
"devDependencies": {
"@nuxtjs/i18n": "latest",
"nuxt": "latest"
}
}
2 changes: 2 additions & 0 deletions src/bundler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ export async function extendBundler(nuxt: Nuxt, nuxtOptions: Required<NuxtI18nOp
runtimeOnly: nuxtOptions.bundle.runtimeOnly,
compositionOnly: nuxtOptions.bundle.compositionOnly,
jitCompilation: nuxtOptions.compilation.jit,
onlyLocales: nuxtOptions.bundle.onlyLocales,
dropMessageCompiler: nuxtOptions.compilation.jit ? nuxtOptions.bundle.dropMessageCompiler : false,
strictMessage: nuxtOptions.compilation.strictMessage,
escapeHtml: nuxtOptions.compilation.escapeHtml
Expand Down Expand Up @@ -88,6 +89,7 @@ export async function extendBundler(nuxt: Nuxt, nuxtOptions: Required<NuxtI18nOp
runtimeOnly: nuxtOptions.bundle.runtimeOnly,
compositionOnly: nuxtOptions.bundle.compositionOnly,
fullInstall: nuxtOptions.bundle.fullInstall,
onlyLocales: nuxtOptions.bundle.onlyLocales,
jitCompilation: nuxtOptions.compilation.jit,
dropMessageCompiler: nuxtOptions.compilation.jit ? nuxtOptions.bundle.dropMessageCompiler : false,
strictMessage: nuxtOptions.compilation.strictMessage,
Expand Down
4 changes: 3 additions & 1 deletion src/module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ import {
getPackageManagerType,
mergeI18nModules,
applyOptionOverrides,
getLocaleFiles
getLocaleFiles,
filterLocales
} from './utils'
import { distDir, runtimeDir, pkgModulesDir } from './dirs'
import { applyLayerOptions, checkLayerOptions, resolveLayerVueI18nConfigInfo } from './layers'
Expand Down Expand Up @@ -127,6 +128,7 @@ export default defineNuxtModule<NuxtI18nOptions>({

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

/**
* setup runtime config
Expand Down
5 changes: 4 additions & 1 deletion src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,10 @@ export interface ExperimentalFeatures {
}

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

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

Expand Down
22 changes: 22 additions & 0 deletions src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,28 @@ export function formatMessage(message: string) {
return `[${NUXT_I18N_MODULE_ID}]: ${message}`
}

export function castArray<T>(value: T | T[]): T[] {
return Array.isArray(value) ? value : [value]
}

export function normalizeIncludingLocales(locales?: string | string[]) {
return (castArray(locales) ?? []).filter(isString)
}

export function filterLocales(options: Required<NuxtI18nOptions>, nuxt: Nuxt) {
const project = getLayerI18n(nuxt.options._layers[0])
const includingLocales = normalizeIncludingLocales(project?.bundle?.onlyLocales)

if (!includingLocales.length) {
return
}

options.locales = options.locales.filter(locale => {
const code = isString(locale) ? locale : locale.code
return includingLocales.includes(code)
}) as string[] | LocaleObject[]
}

export function getNormalizedLocales(locales: NuxtI18nOptions['locales']): LocaleObject[] {
locales = locales || []
const normalized: LocaleObject[] = []
Expand Down

0 comments on commit 1fc1f02

Please sign in to comment.