Add injectAs to work with external plugins

This commit is contained in:
Sebastien Chopin 2017-04-10 18:44:08 +02:00
parent 9c16c0d3f2
commit b11a4d761b
19 changed files with 386 additions and 27 deletions

View File

@ -0,0 +1,3 @@
# i18n with Nuxt.js
https://nuxtjs.org/examples/i18n

View File

@ -0,0 +1,100 @@
<template>
<div>
<header class="Header">
<div class="container">
<h1 class="Header__Title">Nuxt i18n</h1>
<nav class="Header__Menu">
<nuxt-link class="Header__Link" :to="path('/')" exact>
{{ $t('links.home') }}
</nuxt-link>
<nuxt-link class="Header__Link" :to="path('/about')">
{{ $t('links.about') }}
</nuxt-link>
<nuxt-link class="Header__Link" v-if="$i18n.locale === 'en-US'" :to="`/fr-FR` + $route.fullPath" active-class="none">
{{ $t('links.french') }}
</nuxt-link>
<nuxt-link class="Header__Link" v-else :to="$route.fullPath.replace(/^\/[^\/]+/, '')" active-class="none">
{{ $t('links.english') }}
</nuxt-link>
</nav>
</div>
</header>
<nuxt/>
</div>
</template>
<script>
export default {
methods: {
path (url) {
return (this.$i18n.locale === 'en-US' ? url : '/' + this.$i18n.locale + url)
}
}
}
</script>
<style>
html, body
{
background-color: #fff;
color: #2e2f30;
letter-spacing: 0.5px;
font-size: 18px;
font-family: "Source Sans Pro", Arial, sans-serif;
height: 100vh;
margin: 0;
}
*, *:before, *:after
{
padding: 0;
margin: 0;
box-sizing: border-box;
}
.container
{
width: 75%;
margin: 0 auto;
}
.container:after
{
content: "";
display: table;
clear: both;
}
.Header
{
color: #fff;
height: 80px;
line-height: 80px;
background-color: #2e2f30;
}
.Header__Title
{
float: left;
font-weight: 300;
font-size: 30px;
}
.Header__Menu
{
float: right;
}
.Header__Link
{
font-size: 16px;
color: #fff;
border: 1px solid #fff;
padding: 7px 12px;
text-transform: uppercase;
text-decoration: none;
border-radius: 5px;
margin-left: 10px;
}
.Header__Link:hover
{
color: #2e2f30;
background-color: #fff;
}
.nuxt-link-active {
color: cyan;
}
</style>

View File

@ -0,0 +1,59 @@
<template>
<div class="error-page">
<div>
<h1 class="error-code">{{ error.statusCode }}</h1>
<div class="error-wrapper-message">
<h2 class="error-message">{{ error.message }}</h2>
</div>
<p v-if="error.statusCode === 404"><nuxt-link class="error-link" to="/">Back to the home page</nuxt-link></p>
</div>
</div>
</template>
<script>
export default {
props: ['error'],
head () {
return {
title: this.error.message || 'An error occured'
}
}
}
</script>
<style scoped>
.error-page {
color: #000;
font-family: "SF UI Text", "Helvetica Neue", "Lucida Grande";
text-align: center;
padding-top: 20%;
}
.error-code {
display: inline-block;
font-size: 24px;
font-weight: 500;
vertical-align: top;
border-right: 1px solid rgba(0, 0, 0, 0.298039);
margin: 0px 20px 0px 0px;
padding: 10px 23px;
}
.error-wrapper-message {
display: inline-block;
text-align: left;
line-height: 49px;
height: 49px;
vertical-align: middle;
margin-bottom: 20px;
}
.error-message {
font-size: 14px;
font-weight: normal;
margin: 0px;
padding: 0px;
}
.error-link {
color: #000;
font-weight: normal;
font-size: 14px;
}
</style>

View File

@ -0,0 +1,16 @@
{
"links": {
"home": "Home",
"about": "About",
"english": "English version",
"french": "French version"
},
"home": {
"title": "Welcome",
"introduction": "This is an introduction in English."
},
"about": {
"title": "About",
"introduction": "This page is made to give you more informations."
}
}

View File

@ -0,0 +1,16 @@
{
"links": {
"home": "Accueil",
"about": "À propos",
"english": "Version Anglaise",
"french": "Version Française"
},
"home": {
"title": "Bienvenue",
"introduction": "Ceci est un texte d'introduction en Français."
},
"about": {
"title": "À propos",
"introduction": "Cette page est faite pour vous donner plus d'informations."
}
}

View File

@ -0,0 +1,5 @@
export default function ({ app, store, params, error }) {
const locale = params.lang || 'en-US'
store.commit('SET_LANG', locale)
app.$i18n.locale = store.state.locale
}

View File

@ -0,0 +1,14 @@
module.exports = {
loading: {
color: 'cyan'
},
router: {
middleware: 'i18n'
},
build: {
vendor: ['vue-i18n']
},
plugins: [
{ src: '~plugins/i18n.js', injectAs: 'i18n' }
]
}

View File

@ -0,0 +1,12 @@
{
"name": "nuxt-i18n",
"dependencies": {
"axios": "^0.15.3",
"nuxt": "latest"
},
"scripts": {
"dev": "nuxt",
"build": "nuxt build",
"start": "nuxt start"
}
}

View File

@ -0,0 +1,13 @@
<template>
<about/>
</template>
<script>
import About from '~/partials/About.vue'
export default {
components: {
About
}
}
</script>

View File

@ -0,0 +1,13 @@
<template>
<home/>
</template>
<script>
import Home from '~/partials/Home.vue'
export default {
components: {
Home
}
}
</script>

View File

@ -0,0 +1,13 @@
<template>
<about/>
</template>
<script>
import About from '~/partials/About.vue'
export default {
components: {
About
}
}
</script>

View File

@ -0,0 +1,13 @@
<template>
<home/>
</template>
<script>
import Home from '~/partials/Home.vue'
export default {
components: {
Home
}
}
</script>

View File

@ -0,0 +1,21 @@
<template>
<div class="Content">
<div class="container">
<h1 class="Content__Title">{{ $t('about.title') }}</h1>
<p>{{ $t('about.introduction') }}</p>
</div>
</div>
</template>
<style>
.Content
{
padding: 50px 0;
text-align: center;
}
.Content__Title
{
font-weight: 300;
padding-bottom: 30px;
}
</style>

View File

@ -0,0 +1,21 @@
<template>
<div class="Content">
<div class="container">
<h1 class="Content__Title">{{ $t('home.title') }}</h1>
<p>{{ $t('home.introduction') }}</p>
</div>
</div>
</template>
<style>
.Content
{
padding: 50px 0;
text-align: center;
}
.Content__Title
{
font-weight: 300;
padding-bottom: 30px;
}
</style>

View File

@ -0,0 +1,18 @@
import Vue from 'vue'
import VueI18n from 'vue-i18n'
import store from '~store'
Vue.use(VueI18n)
console.log(store.state.locale)
const i18n = new VueI18n({
locale: store.state.locale,
fallbackLocale: 'en-US',
messages: {
'en-US': require('~/locales/en-US.json'),
'fr-FR': require('~/locales/fr-FR.json')
}
})
export default i18n

View File

@ -0,0 +1,11 @@
export const state = {
locale: 'en-US'
}
export const mutations = {
SET_LANG (state, locale) {
if (['en-US', 'fr-FR'].indexOf(locale) !== -1) {
state.locale = locale
}
}
}

View File

@ -42,13 +42,13 @@ if (process.browser) {
// Includes external plugins // Includes external plugins
<% plugins.forEach(function (plugin) { <% plugins.forEach(function (plugin) {
if (typeof plugin === 'string') { %> if (plugin.ssr) { %>
require('<%= plugin %>') <%= (plugin.injectAs ? 'let ' + plugin.injectAs + ' = ' : '') %>require('<%= plugin.src %>')
<% } else if (plugin.src && plugin.ssr !== false) { %> <%= (plugin.injectAs ? plugin.injectAs + ' = ' + plugin.injectAs + '.default || ' + plugin.injectAs : '') %>
require('<%= plugin.src %>') <% } else { %>
<% } else if (plugin.src) { %>
if (process.browser) { if (process.browser) {
require('<%= plugin.src %>') <%= (plugin.injectAs ? 'let ' + plugin.injectAs + ' = ' : '') %>require('<%= plugin.src %>')
<%= (plugin.injectAs ? plugin.injectAs + ' = ' + plugin.injectAs + '.default || ' + plugin.injectAs : '') %>
} }
<% } %> <% } %>
<% }) %> <% }) %>
@ -62,7 +62,7 @@ serialize(transition)
.replace('enterCancelled(', 'function(').replace('beforeLeave(', 'function(').replace('leave(', 'function(') .replace('enterCancelled(', 'function(').replace('beforeLeave(', 'function(').replace('leave(', 'function(')
.replace('afterLeave(', 'function(').replace('leaveCancelled(', 'function(') .replace('afterLeave(', 'function(').replace('leaveCancelled(', 'function(')
%> %>
const app = { let app = {
router, router,
<%= (store ? 'store,' : '') %> <%= (store ? 'store,' : '') %>
_nuxt: { _nuxt: {
@ -100,4 +100,15 @@ const app = {
...App ...App
} }
// Inject external plugins in app
<% plugins.forEach(function (plugin) {
if (plugin.injectAs && plugin.ssr) { %>
app.<%= plugin.injectAs %> = <%= plugin.injectAs %>
<% } else if (plugin.injectAs) { %>
if (process.browser) {
app.<%= plugin.injectAs %> = <%= plugin.injectAs %>
}
<% } %>
<% }) %>
export { app, router<%= (store ? ', store' : '') %>, NuxtError } export { app, router<%= (store ? ', store' : '') %>, NuxtError }

View File

@ -205,7 +205,7 @@ function * generateRoutesAndFiles () {
if (typeof p === 'string') { if (typeof p === 'string') {
return { src: r(this.srcDir, p), ssr: true } return { src: r(this.srcDir, p), ssr: true }
} }
return { src: r(this.srcDir, p.src), ssr: !!p.ssr } return { src: r(this.srcDir, p.src), ssr: (p.ssr === false ? false : true), injectAs: (p.injectAs || false) }
}), }),
appPath: './App.vue', appPath: './App.vue',
layouts: layouts, layouts: layouts,

View File

@ -56,13 +56,13 @@
"babel-core": "^6.24.0", "babel-core": "^6.24.0",
"babel-loader": "^6.4.1", "babel-loader": "^6.4.1",
"babel-preset-es2015": "^6.24.0", "babel-preset-es2015": "^6.24.0",
"babel-preset-vue-app": "^0.5.1", "babel-preset-vue-app": "^1.1.0",
"chokidar": "^1.6.1", "chokidar": "^1.6.1",
"co": "^4.6.0", "co": "^4.6.0",
"compression": "^1.6.2", "compression": "^1.6.2",
"css-loader": "^0.27.3", "css-loader": "^0.28.0",
"debug": "^2.6.3", "debug": "^2.6.3",
"file-loader": "^0.10.1", "file-loader": "^0.11.1",
"friendly-errors-webpack-plugin": "^1.6.1", "friendly-errors-webpack-plugin": "^1.6.1",
"fs-extra": "^2.1.2", "fs-extra": "^2.1.2",
"glob": "^7.1.1", "glob": "^7.1.1",
@ -74,28 +74,28 @@
"memory-fs": "^0.4.1", "memory-fs": "^0.4.1",
"pify": "^2.3.0", "pify": "^2.3.0",
"post-compile-webpack-plugin": "^0.1.1", "post-compile-webpack-plugin": "^0.1.1",
"preload-webpack-plugin": "^1.2.1", "preload-webpack-plugin": "^1.2.2",
"progress-bar-webpack-plugin": "^1.9.3", "progress-bar-webpack-plugin": "^1.9.3",
"script-ext-html-webpack-plugin": "^1.7.1", "script-ext-html-webpack-plugin": "^1.7.1",
"serialize-javascript": "^1.3.0", "serialize-javascript": "^1.3.0",
"serve-static": "^1.12.1", "serve-static": "^1.12.1",
"url-loader": "^0.5.8", "url-loader": "^0.5.8",
"vue": "^2.2.5", "vue": "^2.2.6",
"vue-loader": "^11.3.3", "vue-loader": "^11.3.4",
"vue-meta": "^0.5.5", "vue-meta": "^0.5.6",
"vue-router": "^2.3.0", "vue-router": "^2.3.1",
"vue-server-renderer": "^2.2.5", "vue-server-renderer": "^2.2.6",
"vue-ssr-html-stream": "^2.2.0", "vue-ssr-html-stream": "^2.2.0",
"vue-ssr-webpack-plugin": "^1.0.2", "vue-ssr-webpack-plugin": "^2.1.0",
"vue-template-compiler": "^2.2.5", "vue-template-compiler": "^2.2.6",
"vuex": "^2.2.1", "vuex": "^2.2.1",
"webpack": "^2.3.2", "webpack": "^2.3.3",
"webpack-bundle-analyzer": "^2.3.1", "webpack-bundle-analyzer": "^2.3.1",
"webpack-dev-middleware": "^1.10.1", "webpack-dev-middleware": "^1.10.1",
"webpack-hot-middleware": "^2.17.1" "webpack-hot-middleware": "^2.18.0"
}, },
"devDependencies": { "devDependencies": {
"ava": "^0.18.2", "ava": "^0.19.0",
"babel-eslint": "^7.2.1", "babel-eslint": "^7.2.1",
"babel-plugin-array-includes": "^2.0.3", "babel-plugin-array-includes": "^2.0.3",
"babel-plugin-transform-async-to-generator": "^6.22.0", "babel-plugin-transform-async-to-generator": "^6.22.0",
@ -103,17 +103,17 @@
"babel-preset-stage-2": "^6.22.0", "babel-preset-stage-2": "^6.22.0",
"codecov": "^2.1.0", "codecov": "^2.1.0",
"copy-webpack-plugin": "^4.0.1", "copy-webpack-plugin": "^4.0.1",
"eslint": "^3.18.0", "eslint": "^3.19.0",
"eslint-config-standard": "^8.0.0-beta.2", "eslint-config-standard": "^10.0.0",
"eslint-plugin-html": "^2.0.1", "eslint-plugin-html": "^2.0.1",
"eslint-plugin-import": "^2.2.0", "eslint-plugin-import": "^2.2.0",
"eslint-plugin-node": "^4.2.1", "eslint-plugin-node": "^4.2.2",
"eslint-plugin-promise": "^3.5.0", "eslint-plugin-promise": "^3.5.0",
"eslint-plugin-standard": "^2.1.1", "eslint-plugin-standard": "^2.2.0",
"finalhandler": "^1.0.1", "finalhandler": "^1.0.1",
"jsdom": "^9.12.0", "jsdom": "^9.12.0",
"json-loader": "^0.5.4", "json-loader": "^0.5.4",
"nyc": "^10.2.0-candidate.0", "nyc": "^10.2.0",
"request": "^2.81.0", "request": "^2.81.0",
"request-promise-native": "^1.0.3", "request-promise-native": "^1.0.3",
"webpack-node-externals": "^1.5.4" "webpack-node-externals": "^1.5.4"