Skip to content

Commit

Permalink
feat: support layer locales and pages (#1925)
Browse files Browse the repository at this point in the history
* feat: support layer locales and pages

* fix: locales not merged when lazy is false

* test: add basic layers test

* fix: layer locales not being bundled correctly

* docs: add layers page

* feat: change playground to illustrate layer override behavior

* test: add additional layer tests

* refactor: restructure layers implementation

* fix: update lockfile
  • Loading branch information
BobbieGoede committed Mar 24, 2023
1 parent e65d8f2 commit f36673e
Show file tree
Hide file tree
Showing 36 changed files with 762 additions and 82 deletions.
2 changes: 1 addition & 1 deletion .vscode/settings.json
Expand Up @@ -10,4 +10,4 @@
"source.fixAll.eslint": true
},
"typescript.tsdk": "node_modules/typescript/lib"
}
}
87 changes: 87 additions & 0 deletions docs/content/2.guide/15.layers.md
@@ -0,0 +1,87 @@
# Layers

Nuxt i18n module supports layers and will automatically combine i18n configuration of all extended layers. [Read more about layers here](https://nuxt.com/docs/getting-started/layers)

---

### Merging strategy
As described in the [Nuxt layer authoring guide](https://nuxt.com/docs/guide/going-further/layers#multi-layer-support-for-nuxt-modules)
> * Earlier items in the `_layers` array have higher priority and override later ones
> * The user's project is the first item in the `_layers` array
Mixing locale configuration such as lazy loading objects and strings may not work as expected, Nuxt i18n will attempt to merge layers as best it can. Consistency of i18n configuration between layers will be most effective.


### Pages & Routing

Pages in the `pages` directory from extended layers will automatically be merged and have i18n support as if they were part of your project.

Page routes defined in `i18n.pages` in each layer configuration will be merged as well.

### Locales
::alert{type="warning"}
A project extending layers containing lazy-loaded translations is still required to have `lazy` and `langDir` options configured.
::

Extending your project with a layer that contains locales can be done as follows:

::code-group
::code-block{label="Project config" active}
```ts {} [nuxt.config.ts]
export default defineNuxtConfig({
extends: ['my-layer'],
modules: ['@nuxtjs/i18n'],
i18n: {
lazy: true,
langDir: './lang',
locales: [{ code: 'en', file: 'en.json' }],
},
})
```
::
::code-block{label="Layer config"}
```ts
export default defineNuxtConfig({
modules: ['@nuxtjs/i18n'],
i18n: {
lazy: true,
langDir: './lang',
locales: [
{ code: 'en', file: 'en.json' },
{ code: 'nl', file: 'nl.json' },
],
},
})
```
::
::

This example would result in the project supporting two locales (`en`, `nl`) and would add the additional messages added for the `en` locale.

::code-group
::code-block{label="project/lang/en.json" active}
```ts {} [project/lang/en.json]
{
"title": "foo"
}
```
::
::code-block{label="project/my-layer/lang/en.json"}
```ts {} [project/my-layer/lang/en.json]
{
"title": "layer title",
"description": "bar"
}
```
::
::code-block{label="result en.json"}
```ts {} [result]
{
// earlier layers take priority
"title": "foo",
"description": "bar"
}
```
::
::

File renamed without changes.
3 changes: 3 additions & 0 deletions playground/layers/i18n-layer/locales/en.json
@@ -0,0 +1,3 @@
{
"layerText": "This is a merged locale key"
}
3 changes: 3 additions & 0 deletions playground/layers/i18n-layer/locales/fr.json
@@ -0,0 +1,3 @@
{
"layerText": "This is a merged locale key in French"
}
3 changes: 3 additions & 0 deletions playground/layers/i18n-layer/locales/nl.json
@@ -0,0 +1,3 @@
{
"layerText": "This is a merged locale key in Dutch"
}
62 changes: 62 additions & 0 deletions playground/layers/i18n-layer/nuxt.config.ts
@@ -0,0 +1,62 @@
// import type { NuxtApp } from 'nuxt/dist/app/index'

// https://nuxt.com/docs/guide/directory-structure/nuxt.config
export default defineNuxtConfig({
modules: ['@nuxtjs/i18n'],
i18n: {
langDir: 'locales',
lazy: true,
baseUrl: 'http://localhost:3000',
customRoutes: 'config',
pages: {
history: {
en: '/history',
fr: '/history-fr',
nl: '/geschiedenis'
}
},
locales: [
{
code: 'en',
iso: 'en-US',
file: 'en.json',
// domain: 'localhost',
name: 'English'
},
{
code: 'fr',
iso: 'fr-FR',
file: 'fr.json',
// domain: 'localhost',
name: 'Francais'
},
{
code: 'nl',
iso: 'nl-NL',
file: 'nl.json',
// domain: 'localhost',
name: 'Nederlands'
}
// {
// code: 'en-GB',
// iso: 'en-GB',
// files: ['en.json', 'en-GB.json'],
// name: 'English (UK)'
// },
// {
// code: 'ja',
// iso: 'ja-JP',
// file: 'ja.json',
// domain: 'mydomain.com',
// name: 'Japanses'
// },
// {
// code: 'fr',
// iso: 'fr-FR',
// file: 'fr.json',
// domain: 'mydomain.fr',
// name: 'Français'
// }
]
}
})
9 changes: 9 additions & 0 deletions playground/layers/i18n-layer/pages/about.vue
@@ -0,0 +1,9 @@
<script setup lang="ts">
definePageMeta({
title: 'Empty about page!'
})
</script>

<template>
<div>This about page is empty!</div>
</template>
3 changes: 3 additions & 0 deletions playground/layers/i18n-layer/pages/history.vue
@@ -0,0 +1,3 @@
<template>
<div></div>
</template>
5 changes: 4 additions & 1 deletion playground/nuxt.config.ts
Expand Up @@ -3,8 +3,8 @@ import type { NuxtApp } from 'nuxt/dist/app/index'

// https://nuxt.com/docs/guide/directory-structure/nuxt.config
export default defineNuxtConfig({
extends: ['layers/i18n-layer'],
modules: [Module1, '@nuxtjs/i18n', '@nuxt/devtools'],

vite: {
build: {
minify: false
Expand Down Expand Up @@ -71,6 +71,9 @@ export default defineNuxtConfig({
dynamicRouteParams: true,
// customRoutes: 'config',
pages: {
history: {
ja: '/history-ja'
},
about: {
ja: '/about-ja'
}
Expand Down
5 changes: 4 additions & 1 deletion playground/pages/index.vue
Expand Up @@ -18,6 +18,8 @@ console.log('route base name', getRouteBaseName())
console.log('useBrowserLocale', useBrowserLocale())
console.log('localeProperties', localeProperties)
console.log('foo', t('foo'))
console.log('message if local layer merged:', t('layerText'))
console.log('message if github layer merged:', t('layer-test-key'))
function getLocaleName(code: string) {
const locale = (locales.value as LocaleObject[]).find(i => i.code === code)
Expand Down Expand Up @@ -54,7 +56,8 @@ definePageMeta({
<nav>
<NuxtLink :to="localePath('/')">Home</NuxtLink> | <NuxtLink :to="localePath({ name: 'about' })">About</NuxtLink> |
<NuxtLink :to="localePath({ name: 'blog' })">Blog</NuxtLink> |
<NuxtLink :to="localePath({ name: 'category-id', params: { id: 'foo' } })">Category</NuxtLink>
<NuxtLink :to="localePath({ name: 'category-id', params: { id: 'foo' } })">Category</NuxtLink> |
<NuxtLink :to="localePath({ name: 'history' })">History</NuxtLink>
</nav>
<h2>Current Language: {{ getLocaleName(locale) }}</h2>
<h2>Current Strategy: {{ strategy }}</h2>
Expand Down

0 comments on commit f36673e

Please sign in to comment.