diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 8771c64b9..b1dc0afab 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -9,10 +9,10 @@ env:
on:
push:
branches:
- - main
+ - v8
pull_request:
branches:
- - main
+ - v8
jobs:
lint:
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index bb002b48b..d85e769dc 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -52,7 +52,7 @@ jobs:
- name: Commit changelog
uses: stefanzweifel/git-auto-commit-action@v5
with:
- branch: main
+ branch: v8
file_pattern: 'CHANGELOG.md'
commit_message: 'chore: generate changelog'
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 346326867..ed979d7cb 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,25 @@
+# v8.3.3 (2024-07-28T09:51:21Z)
+
+This changelog is generated by [GitHub Releases](https://github.com/nuxt-modules/i18n/releases/tag/v8.3.3)
+
+### 🐞 Bug Fixes
+
+- Encode `switchLocalePath` during SSR replacement - by @BobbieGoede in https://github.com/nuxt-modules/i18n/issues/3043 [(28d22)](https://github.com/nuxt-modules/i18n/commit/28d22aa6)
+
+##### [View changes on GitHub](https://github.com/nuxt-modules/i18n/compare/v8.3.2...v8.3.3)
+
+# v8.3.2 (2024-07-27T04:42:45Z)
+
+This changelog is generated by [GitHub Releases](https://github.com/nuxt-modules/i18n/releases/tag/v8.3.2)
+
+### 🐞 Bug Fixes
+
+- Update `@nuxt/module-builder` - by @BobbieGoede in https://github.com/nuxt-modules/i18n/issues/2960 [(fe300)](https://github.com/nuxt-modules/i18n/commit/fe300294)
+- Locale prefixes are not added to route aliases - by @BobbieGoede in https://github.com/nuxt-modules/i18n/issues/2962 [(62236)](https://github.com/nuxt-modules/i18n/commit/62236964)
+- Unable to configure server integration using inline options - by @BobbieGoede in https://github.com/nuxt-modules/i18n/issues/3020 [(856ba)](https://github.com/nuxt-modules/i18n/commit/856ba4fc)
+
+##### [View changes on GitHub](https://github.com/nuxt-modules/i18n/compare/v8.3.1...v8.3.2)
+
# v8.3.1 (2024-04-24T10:05:08Z)
This changelog is generated by [GitHub Releases](https://github.com/nuxt-modules/i18n/releases/tag/v8.3.1)
diff --git a/package.json b/package.json
index 2b2d411b5..ca590cce5 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
{
"name": "@nuxtjs/i18n",
"description": "i18n for Nuxt",
- "version": "8.3.1",
+ "version": "8.3.3",
"homepage": "https://i18n.nuxtjs.org",
"bugs": {
"url": "https://github.com/nuxt-community/i18n-module/issues"
diff --git a/playground/pages/index.vue b/playground/pages/index.vue
index 45f6898eb..9d1e03fd7 100644
--- a/playground/pages/index.vue
+++ b/playground/pages/index.vue
@@ -1,5 +1,6 @@
<`
+
+ const html = await $fetch(url)
+ const dom = getDom(html)
+
+ // the localized should be the same as encoded
+ expect(dom.querySelector('#slp-xss a').href).toEqual(encodeURI('/nl' + url))
+ })
})
diff --git a/specs/fixtures/basic_usage/app.vue b/specs/fixtures/basic_usage/app.vue
index c0937df0c..fcb7faf7f 100644
--- a/specs/fixtures/basic_usage/app.vue
+++ b/specs/fixtures/basic_usage/app.vue
@@ -1,6 +1,6 @@
+
+
+ No XSS
+
+
diff --git a/specs/fixtures/inline_options/locale-detector.ts b/specs/fixtures/inline_options/locale-detector.ts
new file mode 100644
index 000000000..4cce000e8
--- /dev/null
+++ b/specs/fixtures/inline_options/locale-detector.ts
@@ -0,0 +1,23 @@
+// Detect based on query, cookie, header
+export default defineI18nLocaleDetector((event, config) => {
+ // try to get locale from query
+ const query = tryQueryLocale(event, { lang: '' }) // disable locale default value with `lang` option
+ if (query) {
+ return query.toString()
+ }
+
+ // try to get locale from cookie
+ const cookie = tryCookieLocale(event, { lang: '', name: 'i18n_locale' }) // disable locale default value with `lang` option
+ if (cookie) {
+ return cookie.toString()
+ }
+
+ // try to get locale from header (`accept-header`)
+ const header = tryHeaderLocale(event, { lang: '' }) // disable locale default value with `lang` option
+ if (header) {
+ return header.toString()
+ }
+
+ // If the locale cannot be resolved up to this point, it is resolved with the value `defaultLocale` of the locale config passed to the function
+ return config.defaultLocale
+})
diff --git a/specs/fixtures/inline_options/nuxt.config.ts b/specs/fixtures/inline_options/nuxt.config.ts
index 9712bcec9..5b955a318 100644
--- a/specs/fixtures/inline_options/nuxt.config.ts
+++ b/specs/fixtures/inline_options/nuxt.config.ts
@@ -19,7 +19,10 @@ export default defineNuxtConfig({
file: 'locale-file-en.json',
name: 'English'
}
- ]
+ ],
+ experimental: {
+ localeDetector: './locale-detector.ts'
+ }
}
]
],
diff --git a/specs/fixtures/inline_options/server/api/translate.ts b/specs/fixtures/inline_options/server/api/translate.ts
new file mode 100644
index 000000000..1eae6c186
--- /dev/null
+++ b/specs/fixtures/inline_options/server/api/translate.ts
@@ -0,0 +1,7 @@
+import { useTranslation } from '@intlify/h3'
+
+export default defineEventHandler(async event => {
+ const t = await useTranslation(event)
+
+ return t('home')
+})
diff --git a/specs/inline_options.spec.ts b/specs/inline_options.spec.ts
index 4c7717d69..2cbb66080 100644
--- a/specs/inline_options.spec.ts
+++ b/specs/inline_options.spec.ts
@@ -1,6 +1,6 @@
import { test, expect, describe } from 'vitest'
import { fileURLToPath } from 'node:url'
-import { setup } from './utils'
+import { setup, url, $fetch } from './utils'
import { renderPage } from './helper'
await setup({
@@ -34,4 +34,9 @@ describe('inline options are handled correctly', async () => {
)
).toBe(false)
})
+
+ test('(#2721) server integration from inline configuration', async () => {
+ const res = await $fetch(url('/api/translate'))
+ expect(res).toEqual('Homepage')
+ })
})
diff --git a/src/constants.ts b/src/constants.ts
index ba59587c5..83697b1ab 100644
--- a/src/constants.ts
+++ b/src/constants.ts
@@ -66,7 +66,8 @@ export const DEFAULT_OPTIONS = {
cookieSecure: false,
fallbackLocale: '',
redirectOn: 'root',
- useCookie: true
+ useCookie: true,
+ httpOnly: false,
},
differentDomains: false,
baseUrl: '',
diff --git a/src/module.ts b/src/module.ts
index 7e9c3a21f..295905a0a 100644
--- a/src/module.ts
+++ b/src/module.ts
@@ -234,6 +234,7 @@ export default defineNuxtModule({
// for core plugin
addPlugin(resolve(runtimeDir, 'plugins/i18n'))
+ addPlugin(resolve(runtimeDir, 'plugins/switch-locale-path-ssr'))
// for composables
nuxt.options.alias['#i18n'] = resolve(distDir, 'runtime/composables/index.mjs')
diff --git a/src/nitro.ts b/src/nitro.ts
index a1100d725..25dd14938 100644
--- a/src/nitro.ts
+++ b/src/nitro.ts
@@ -7,7 +7,7 @@ import { addServerPlugin, createResolver, resolvePath, useLogger } from '@nuxt/k
import yamlPlugin from '@rollup/plugin-yaml'
import json5Plugin from '@miyaneee/rollup-plugin-json5'
import { getFeatureFlags } from './bundler'
-import { isExists } from './utils'
+import { getLayerI18n, isExists } from './utils'
import {
H3_PKG,
UTILS_H3_PKG,
@@ -131,13 +131,16 @@ export { localeDetector }
}
async function resolveLocaleDetectorPath(nuxt: Nuxt) {
- const serverI18nLayer = nuxt.options._layers.find(
- l => l.config.i18n?.experimental?.localeDetector != null && l.config.i18n?.experimental?.localeDetector !== ''
- )
+ const serverI18nLayer = nuxt.options._layers.find(l => {
+ const layerI18n = getLayerI18n(l)
+ return layerI18n?.experimental?.localeDetector != null && layerI18n?.experimental?.localeDetector !== ''
+ })
+
let enableServerIntegration = serverI18nLayer != null
if (serverI18nLayer != null) {
- const pathTo = resolve(serverI18nLayer.config.rootDir, serverI18nLayer.config.i18n!.experimental!.localeDetector!)
+ const serverI18nLayerConfig = getLayerI18n(serverI18nLayer)
+ const pathTo = resolve(serverI18nLayer.config.rootDir, serverI18nLayerConfig!.experimental!.localeDetector!)
const localeDetectorPath = await resolvePath(pathTo, {
cwd: nuxt.options.rootDir,
extensions: EXECUTABLE_EXTENSIONS
diff --git a/src/runtime/components/SwitchLocalePathLink.ts b/src/runtime/components/SwitchLocalePathLink.ts
index 906a04fbd..3166d0cce 100644
--- a/src/runtime/components/SwitchLocalePathLink.ts
+++ b/src/runtime/components/SwitchLocalePathLink.ts
@@ -21,7 +21,7 @@ export default defineComponent({
return () => [
h(Comment, `${SWITCH_LOCALE_PATH_LINK_IDENTIFIER}-[${props.locale}]`),
- h(NuxtLink, { ...attrs, to: switchLocalePath(props.locale) }, slots.default),
+ h(NuxtLink, { ...attrs, to: encodeURI(switchLocalePath(props.locale)) }, slots.default),
h(Comment, `/${SWITCH_LOCALE_PATH_LINK_IDENTIFIER}`)
]
}
diff --git a/src/runtime/internal.ts b/src/runtime/internal.ts
index c2d8eaa37..83290ba51 100644
--- a/src/runtime/internal.ts
+++ b/src/runtime/internal.ts
@@ -99,7 +99,8 @@ export function getI18nCookie() {
expires: new Date(date.setDate(date.getDate() + 365)),
path: '/',
sameSite: detect && detect.cookieCrossOrigin ? 'none' : 'lax',
- secure: (detect && detect.cookieCrossOrigin) || (detect && detect.cookieSecure)
+ secure: (detect && detect.cookieCrossOrigin) || (detect && detect.cookieSecure),
+ httpOnly: detect && detect.httpOnly ? true : false
}
if (detect && detect.cookieDomain) {
diff --git a/src/runtime/plugins/i18n.ts b/src/runtime/plugins/i18n.ts
index dcc80e995..18d968e2e 100644
--- a/src/runtime/plugins/i18n.ts
+++ b/src/runtime/plugins/i18n.ts
@@ -7,11 +7,9 @@ import {
isSSG,
localeLoaders,
parallelPlugin,
- normalizedLocales,
- SWITCH_LOCALE_PATH_LINK_IDENTIFIER
+ normalizedLocales
} from '#build/i18n.options.mjs'
import { loadVueI18nOptions, loadInitialMessages, loadLocale } from '../messages'
-import { useSwitchLocalePath } from '../composables'
import {
loadAndSetLocale,
detectLocale,
@@ -401,29 +399,6 @@ export default defineNuxtPlugin({
// inject for nuxt helpers
injectNuxtHelpers(nuxtContext, i18n)
- // Replace `SwitchLocalePathLink` href in rendered html for SSR support
- if (runtimeI18n.experimental.switchLocalePathLinkSSR === true) {
- const switchLocalePath = useSwitchLocalePath()
-
- const switchLocalePathLinkWrapperExpr = new RegExp(
- [
- ``,
- `.+?`,
- ``
- ].join(''),
- 'g'
- )
-
- nuxt.hook('app:rendered', ctx => {
- if (ctx.renderResult?.html == null) return
-
- ctx.renderResult.html = ctx.renderResult.html.replaceAll(
- switchLocalePathLinkWrapperExpr,
- (match: string, p1: string) => match.replace(/href="([^"]+)"/, `href="${switchLocalePath(p1 ?? '')}"`)
- )
- })
- }
-
let routeChangeCount = 0
addRouteMiddleware(
diff --git a/src/runtime/plugins/switch-locale-path-ssr.ts b/src/runtime/plugins/switch-locale-path-ssr.ts
new file mode 100644
index 000000000..598665889
--- /dev/null
+++ b/src/runtime/plugins/switch-locale-path-ssr.ts
@@ -0,0 +1,33 @@
+import { defineNuxtPlugin } from '#imports'
+import { useSwitchLocalePath } from '#i18n'
+import { SWITCH_LOCALE_PATH_LINK_IDENTIFIER } from '#build/i18n.options.mjs'
+
+// Replace `SwitchLocalePathLink` href in rendered html for SSR support
+export default defineNuxtPlugin({
+ name: 'i18n:plugin:switch-locale-path-ssr',
+ dependsOn: ['i18n:plugin'],
+ setup(nuxt) {
+ if (nuxt.$config.public.i18n.experimental.switchLocalePathLinkSSR !== true) return
+
+ const switchLocalePath = useSwitchLocalePath()
+
+ const switchLocalePathLinkWrapperExpr = new RegExp(
+ [
+ ``,
+ `.+?`,
+ ``
+ ].join(''),
+ 'g'
+ )
+
+ nuxt.hook('app:rendered', ctx => {
+ if (ctx.renderResult?.html == null) return
+
+ ctx.renderResult.html = ctx.renderResult.html.replaceAll(
+ switchLocalePathLinkWrapperExpr,
+ (match: string, p1: string) =>
+ match.replace(/href="([^"]+)"/, `href="${encodeURI(switchLocalePath(p1 ?? ''))}"`)
+ )
+ })
+ }
+})
diff --git a/src/runtime/routing/extends/router.ts b/src/runtime/routing/extends/router.ts
index 3f90a4b90..17c6e331d 100644
--- a/src/runtime/routing/extends/router.ts
+++ b/src/runtime/routing/extends/router.ts
@@ -3,7 +3,7 @@ import { getLocalesRegex } from '../utils'
import { localeCodes } from '#build/i18n.options.mjs'
import type { RouteLocationNormalized, RouteLocationNormalizedLoaded } from 'vue-router'
-import { useRuntimeConfig } from 'nuxt/app'
+import { useRuntimeConfig } from '#imports'
export function createLocaleFromRouteGetter() {
const { routesNameSeparator, defaultLocaleRouteNameSuffix } = useRuntimeConfig().public.i18n
diff --git a/src/types.ts b/src/types.ts
index d7b479d48..092e6bf63 100644
--- a/src/types.ts
+++ b/src/types.ts
@@ -14,7 +14,8 @@ export interface DetectBrowserLanguageOptions {
cookieSecure?: boolean
fallbackLocale?: Locale | null
redirectOn?: RedirectOnOptions
- useCookie?: boolean
+ useCookie?: boolean,
+ httpOnly?: boolean
}
export type LocaleType = 'static' | 'dynamic' | 'unknown'