nuxt-i18n
Advanced tools
Comparing version 0.1.0 to 1.0.0
const { resolve } = require('path') | ||
const merge = require('lodash/merge') | ||
const i18nExtensions = require('vue-i18n-extensions') | ||
const { generateRoutes } = require('./routes') | ||
@@ -9,10 +10,2 @@ | ||
// Backward compatibility with 0.0.1 | ||
if (options.fallbackLocale && !options.vueI18n.fallbackLocale) { | ||
options.vueI18n.fallbackLocale = options.fallbackLocale | ||
} | ||
if (options.messages && !options.vueI18n.messages) { | ||
options.vueI18n.messages = options.messages | ||
} | ||
this.extendRoutes((routes) => { | ||
@@ -39,9 +32,3 @@ const newRoutes = generateRoutes({ | ||
src: resolve(__dirname, './templates/i18n.routing.plugin.js'), | ||
fileName: 'i18n.routing.plugin.js' | ||
}) | ||
// Store module | ||
this.addTemplate({ | ||
src: resolve(__dirname, './templates/i18n.store.js'), | ||
fileName: 'i18n.store.js', | ||
fileName: 'i18n.routing.plugin.js', | ||
options | ||
@@ -57,2 +44,7 @@ }) | ||
this.options.router.middleware.push('i18n') | ||
this.options.build.vendor.push('vue-i18n') | ||
this.options.render.bundleRenderer.directives = this.options.render.bundleRenderer.directives || {} | ||
this.options.render.bundleRenderer.directives.t = i18nExtensions.directive | ||
} |
@@ -12,2 +12,6 @@ const { has } = require('lodash') | ||
const generateRoutes = ({ baseRoutes, locales, defaultLocale, routesOptions }) => { | ||
// Abort routes generation if no routes or locales specified | ||
if (!baseRoutes || !locales) { | ||
return [] | ||
} | ||
const newRoutes = [] | ||
@@ -14,0 +18,0 @@ baseRoutes.forEach((baseRoute) => { |
import Vue from 'vue' | ||
import VueI18n from 'vue-i18n' | ||
import i18nStore from './i18n.store' | ||
Vue.use(VueI18n) | ||
export default ({ app, store, route, isClient, hotReload }) => { | ||
store.registerModule('i18n', i18nStore) | ||
export default ({ app, route, error }) => { | ||
const i18n = new VueI18n(<%= JSON.stringify(options.vueI18n) %>) | ||
i18n.locale = store.state.i18n.currentLocale | ||
app.i18n = i18n | ||
// Check locale in URL (same as middleware but exclusive to client) | ||
if (isClient) { | ||
const locales = <%= JSON.stringify(options.locales) %> | ||
const defaultLocale = '<%= options.defaultLocale %>' | ||
// Check if middleware called from hot-reloading, ignore | ||
if (hotReload) return | ||
// Get locale from params | ||
let locale = defaultLocale | ||
locales.forEach(l => { | ||
const regexp = new RegExp('^/' + l.code + '/') | ||
if (route.path.match(regexp)) { | ||
locale = l.code | ||
} | ||
}) | ||
if (locales.findIndex(l => l.code === locale) === -1) { | ||
return error({ message: 'Page not found.', statusCode: 404 }) | ||
app.i18n.locales = <%= JSON.stringify(options.locales) %> | ||
app.i18n.defaultLocale = '<%= options.defaultLocale %>' | ||
// Get locale from params | ||
let locale = app.i18n.defaultLocale || null | ||
app.i18n.locales.forEach(l => { | ||
const regexp = new RegExp('^/' + l.code + '/') | ||
if (route.path.match(regexp)) { | ||
locale = l.code | ||
} | ||
if (locale === store.state.i18n.currentLocale) return | ||
// Set locale | ||
store.dispatch('i18n/setLocale', { locale }) | ||
app.i18n.locale = locale | ||
}) | ||
if (app.i18n.locales.findIndex(l => l.code === locale) === -1) { | ||
return error({ message: 'Page not found.', statusCode: 404 }) | ||
} | ||
app.i18n.locale = locale | ||
} |
import middleware from './middleware' | ||
middleware['i18n'] = function authMiddleware ({ app, store, route, error, hotReload, isServer }) { | ||
middleware['i18n'] = function ({ app, route, error, hotReload }) { | ||
const locales = <%= JSON.stringify(options.locales) %> | ||
@@ -19,6 +19,4 @@ const defaultLocale = '<%= options.defaultLocale %>' | ||
} | ||
if (locale === store.state.i18n.currentLocale) return | ||
// Set locale | ||
store.dispatch('i18n/setLocale', { locale }) | ||
if (locale === app.i18n.locale) return | ||
app.i18n.locale = locale | ||
} |
@@ -6,3 +6,3 @@ import './i18n.routing.middleware'; | ||
methods: { | ||
getLocalizedRoute (route, locale) { | ||
localePath (route, locale) { | ||
if (!route) return | ||
@@ -21,3 +21,3 @@ locale = locale || this.$i18n.locale | ||
let { href } = resolved | ||
// Handle exception for homepage | ||
// Handle homepage exception | ||
if (route.name === 'index') { | ||
@@ -30,2 +30,10 @@ href += '/' | ||
}, | ||
switchLocalePath (locale) { | ||
const name = this.getRouteBaseName() | ||
if (!name) { | ||
return '' | ||
} | ||
const baseRoute = Object.assign({}, this.$route, { name }) | ||
return this.localePath(baseRoute, locale) | ||
}, | ||
getRouteBaseName (route) { | ||
@@ -36,3 +44,3 @@ route = route || this.$route | ||
} | ||
const locales = this.$store.state.i18n.locales | ||
const locales = <%= JSON.stringify(options.locales) %> | ||
for (let i = locales.length - 1; i >= 0; i--) { | ||
@@ -44,12 +52,4 @@ const regexp = new RegExp('-' + locales[i].code) | ||
} | ||
}, | ||
getSwitchLocaleRoute (locale) { | ||
const name = this.getRouteBaseName() | ||
if (!name) { | ||
return '' | ||
} | ||
const baseRoute = Object.assign({}, this.$route, { name }) | ||
return this.getLocalizedRoute(baseRoute, locale) | ||
} | ||
} | ||
}) |
{ | ||
"name": "nuxt-i18n", | ||
"version": "0.1.0", | ||
"version": "1.0.0", | ||
"description": "i18n for Nuxt", | ||
"license": "MIT", | ||
"contributors": [ | ||
{ | ||
"name": "Paul Gascou-Vaillancourt (@paulgv)" | ||
} | ||
], | ||
"main": "lib/module.js", | ||
"license": "MIT", | ||
"repository": "https://github.com/paulgv/nuxt-i18n", | ||
"publishConfig": { | ||
"access": "public" | ||
}, | ||
"scripts": { | ||
"eslint": "eslint --ext .js ./lib" | ||
"lint": "eslint lib test", | ||
"test": "npm run lint && jest", | ||
"release": "standard-version && git push --follow-tags && npm publish" | ||
}, | ||
"eslintIgnore": [ | ||
"lib/templates" | ||
"lib/templates/*.*" | ||
], | ||
"files": [ | ||
"lib" | ||
], | ||
"jest": { | ||
"testEnvironment": "node", | ||
"coverageDirectory": "./coverage/", | ||
"collectCoverage": true, | ||
"collectCoverageFrom": [ | ||
"lib", | ||
"test" | ||
] | ||
}, | ||
"dependencies": { | ||
"lodash": "^4.17.4", | ||
"vue-i18n": "^7.3.2" | ||
"vue-i18n": "^7.3.2", | ||
"vue-i18n-extensions": "^0.1.0" | ||
}, | ||
"devDependencies": { | ||
"eslint": "^4.10.0", | ||
"eslint-config-standard": "^10.2.1", | ||
"eslint-plugin-import": "^2.8.0", | ||
"eslint-plugin-node": "^5.2.1", | ||
"eslint-plugin-promise": "^3.6.0", | ||
"eslint-plugin-standard": "^3.0.1" | ||
"nuxt-module-builder": "latest" | ||
} | ||
} |
207
README.md
# nuxt-i18n | ||
[![npm (scoped with tag)](https://img.shields.io/npm/v/nuxt-i18n/latest.svg?style=flat-square)](https://npmjs.com/package/nuxt-i18n) | ||
[![npm](https://img.shields.io/npm/dt/nuxt-i18n.svg?style=flat-square)](https://npmjs.com/package/nuxt-i18n) | ||
[![CircleCI](https://img.shields.io/circleci/project/github/paulgv/nuxt-i18n.svg?style=flat-square)](https://circleci.com/gh/paulgv/nuxt-i18n) | ||
[![Codecov](https://img.shields.io/codecov/c/github/paulgv/nuxt-i18n.svg?style=flat-square)](https://codecov.io/gh/paulgv/nuxt-i18n) | ||
[![Dependencies](https://david-dm.org/paulgv/nuxt-i18n/status.svg?style=flat-square)](https://david-dm.org/paulgv/nuxt-i18n) | ||
[![js-standard-style](https://img.shields.io/badge/code_style-standard-brightgreen.svg?style=flat-square)](http://standardjs.com) | ||
> Add i18n to your [Nuxt](https://github.com/nuxt/nuxt.js) application | ||
> i18n for [Nuxt](https://github.com/nuxt/nuxt.js) | ||
This module attempts to provide i18n features to Nuxt applications by installing and enabling [vue-i18n](https://github.com/kazupon/vue-i18n) as well as providing routing helpers to help you customize URLs for your languages. | ||
[📖 **Release Notes**](./CHANGELOG.md) | ||
> This module is a compilation of work that was developed to address some specific needs and it might not work as expected in other setups. | ||
> Any help to improve the module and/or its documentation would be very appreciated! | ||
## Features | ||
## Demo | ||
This module attempts to provide i18n features to Nuxt applications by installing and enabling [vue-i18n](https://github.com/kazupon/vue-i18n) as well as providing routing helpers to help you customize URLs for your languages. | ||
Have a look at the example project to see the module in action: [nuxt-i18n-example](https://github.com/paulgv/nuxt-i18n-example) | ||
## Setup | ||
- Add `nuxt-i18n` dependency using yarn or npm to your project | ||
## Install | ||
Install the module using Yarn or NPM: | ||
```sh | ||
yarn add nuxt-i18n # or npm i nuxt-i18n -S | ||
yarn add nuxt-i18n | ||
# npm i nuxt-i18n -S | ||
``` | ||
Add **nuxt-i18n** to Nuxt's config: | ||
- Add `nuxt-i18n` to `modules` section of `nuxt.config.js` | ||
```js | ||
// nuxt.config.js | ||
module.exports = { | ||
modules: ['nuxt-i18n'] | ||
} | ||
``` | ||
## Configuration | ||
The module can be configured directly in the `modules` key: | ||
```js | ||
// nuxt.config.js | ||
module.exports = { | ||
{ | ||
modules: [ | ||
['nuxt-i18n', { | ||
// options | ||
}] | ||
] | ||
['nuxt-i18n', { /* module options */ }], | ||
] | ||
} | ||
``` | ||
Or via the `i18n` key: | ||
## Usage | ||
```js | ||
// nuxt.config.js | ||
### Available languages | ||
module.exports = { | ||
modules: ['nuxt-i18n'], | ||
i18n: { | ||
// options | ||
} | ||
} | ||
``` | ||
To configure your app's languages, use the `locales` option and the `defaultLocale` option if needed: | ||
## Configuration example | ||
Here's an example configuration for an app that supports English and French, with English as the default and fallback language and some custom routes. You'll probably want to split the configuration accross multiple files to prevent bloating `nuxt.config.js`. | ||
```js | ||
// nuxt.config.js | ||
module.exports = { | ||
{ | ||
modules: [ | ||
@@ -84,2 +58,28 @@ ['nuxt-i18n', { | ||
defaultLocale: 'en', | ||
// ... | ||
}] | ||
] | ||
} | ||
``` | ||
These locales are used to generate the app's routes, the `code` will be used as the URL prefix (except for the default locale). | ||
`locales` and `defaultLocale` are both added to `app.i18n` which means you can refer to them in any component via the `$i18n` property: | ||
```vue | ||
<nuxt-link | ||
v-for="(locale, index) in $i18n.locales" | ||
v-if="locale.code !== $i18n.locale" | ||
:key="index" | ||
:exact="true" | ||
:to="switchLocalePath(locale.code)">{{ locale.name }}</nuxt-link> | ||
``` | ||
### Translations | ||
Messages translation is achieved by **vue-i18n** which you can configure via the `vueI18n` option: | ||
```js | ||
{ | ||
modules: [ | ||
['nuxt-i18n', { | ||
vueI18n: { | ||
@@ -98,16 +98,5 @@ messages: { | ||
}, | ||
fallbackLocale: 'en', | ||
fallbackLocale: 'en' | ||
} | ||
routes: { | ||
about: { | ||
fr: '/a-propos', | ||
en: '/about-us' | ||
}, | ||
category: { | ||
fr: '/categorie' | ||
}, | ||
'category-slug': { | ||
fr: '/categorie/:slug' | ||
} | ||
} | ||
// ... | ||
}] | ||
@@ -118,14 +107,12 @@ ] | ||
## Usage | ||
Refer to [vue-i18n's doc](https://kazupon.github.io/vue-i18n/en/) for more info. | ||
### Translations | ||
### Routing | ||
Messages translation is achieved by **vue-i18n** using the `messages` passed in the module's configuration. Refer to [vue-i18n's doc](https://kazupon.github.io/vue-i18n/en/) for more info. | ||
**nuxt-i18n** overrides Nuxt default routes to add locale prefixes to every URL. | ||
### Routing | ||
> If you define a `defaultLocale`, the URL prefix is omitted for this language | ||
This module overrides Nuxt default routes to add locale prefixes to every page. | ||
Say your app supports English (as the default language) and French, and you have this files structure for your pages: | ||
Let's say your app supports English (default) and French, and you have this files structure for your pages: | ||
``` | ||
@@ -164,13 +151,13 @@ pages/ | ||
You can also customize the path for each route/language using the `routes` key in your configuration (see configuration example above). | ||
You can also customize the path for each route/language using the `routes` key in your configuration, this can be useful if you want to have different paths depending on the user's language (see configuration example below). | ||
In the app, you'll need to preserve the language option when showing links. To do this, this module registers a global mixin that provides some helper functions: | ||
In the app, you'll need to preserve the language when generating URLs. To do this, **nuxt-i18n** registers a global mixin that provides some helper functions: | ||
- `getLocalizedRoute` – Returns the localized URL for a given page. The first parameter can be either the name of the route or an object for more complex routes. A locale code can be passed as the second parameter to generate a link for a specific language: | ||
- `localePath` – Returns the localized URL for a given page. The first parameter can be either the name of the route or an object for more complex routes. A locale code can be passed as the second parameter to generate a link for a specific language: | ||
```vue | ||
<nuxt-link :to="getLocalizedRoute('index')">{{ $t('home') }}</nuxt-link> | ||
<nuxt-link :to="getLocalizedRoute('index', 'en')">Homepage in English</nuxt-link> | ||
<nuxt-link :to="localePath('index')">{{ $t('home') }}</nuxt-link> | ||
<nuxt-link :to="localePath('index', 'en')">Homepage in English</nuxt-link> | ||
<nuxt-link | ||
:to="getLocalizedRoute({ name: 'category-slug', params: { slug: category.slug } })"> | ||
:to="localePath({ name: 'category-slug', params: { slug: category.slug } })"> | ||
{{ category.title }} | ||
@@ -180,13 +167,15 @@ </nuxt-link> | ||
> Note that `getLocalizedRoute` uses the route's base name to generate the localized URL. The base name corresponds to the names Nuxt generates when parsing your `pages/` directory, more info in [Nuxt's doc](https://nuxtjs.org/guide/routing). | ||
> Note that `localePath` uses the route's base name to generate the localized URL. The base name corresponds to the names Nuxt generates when parsing your `pages/` directory, more info in [Nuxt's doc](https://nuxtjs.org/guide/routing). | ||
- `getSwitchLocaleRoute` – Returns a link to the current page for another language passed: | ||
- `switchLocalePath` – Returns a link to the current page in another language: | ||
```vue | ||
<nuxt-link :to="getSwitchLocaleRoute('en')">English</nuxt-link> | ||
<nuxt-link :to="getSwitchLocaleRoute('fr')">Français</nuxt-link> | ||
<nuxt-link :to="switchLocalePath('en')">English</nuxt-link> | ||
<nuxt-link :to="switchLocalePath('fr')">Français</nuxt-link> | ||
``` | ||
> You might want to add `:exact=true` to your `<nuxt-link>` to prevent the `active-class` from being added somewhere you did not expect | ||
## Options | ||
@@ -200,1 +189,63 @@ | ||
| `routes` | Object | Custom routing configuration, if routes are omitted, Nuxt's default routes are used | | ||
## Configuration example | ||
Here's an example configuration for an app that supports English and French, with English as the default and fallback language and some custom routes. You'll probably want to split the configuration accross multiple files to avoid bloating `nuxt.config.js`. | ||
```js | ||
// nuxt.config.js | ||
module.exports = { | ||
modules: [ | ||
['nuxt-i18n', { | ||
locales: [ | ||
{ | ||
code: 'en', | ||
iso: 'en-US', | ||
name: 'English' | ||
}, | ||
{ | ||
code: 'fr', | ||
iso: 'fr-FR', | ||
name: 'Français' | ||
} | ||
], | ||
defaultLocale: 'en', | ||
vueI18n: { | ||
messages: { | ||
fr: { | ||
home: 'Accueil', | ||
about: 'À propos', | ||
category: 'Catégorie' | ||
}, | ||
en: { | ||
home: 'Homepage', | ||
about: 'About us', | ||
category: 'Category' | ||
} | ||
}, | ||
fallbackLocale: 'en' | ||
}, | ||
routes: { | ||
about: { | ||
fr: '/a-propos', | ||
en: '/about-us' | ||
}, | ||
category: { | ||
fr: '/categorie' | ||
}, | ||
'category-slug': { | ||
fr: '/categorie/:slug' | ||
} | ||
} | ||
}] | ||
] | ||
} | ||
``` | ||
## License | ||
[MIT License](./LICENSE) | ||
Copyright (c) Paul Gascou-Vaillancourt (@paulgv) |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Native code
Supply chain riskContains native code (e.g., compiled binaries or shared libraries). Including native code can obscure malicious behavior.
Found 2 instances in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
No contributors or author data
MaintenancePackage does not specify a list of contributors or an author in package.json.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
28452
1
1
1
246
178
2
+ Addedvue-i18n-extensions@^0.1.0
+ Addedacorn@8.14.0(transitive)
+ Addedacorn-walk@8.3.4(transitive)
+ Addedvm2@3.9.19(transitive)
+ Addedvue-i18n-extensions@0.1.0(transitive)
- Removedlodash@^4.17.4
- Removedlodash@4.17.21(transitive)