Skip to content

Commit

Permalink
feat: support external configuration file for vue-i18n options (#605)
Browse files Browse the repository at this point in the history
Added support for specifying path to local file for options passed to
vue-i18n (the `vueI18n` key of `nuxt-i18n` configuration). This allows
for configuration some options that have function type which previously
would fail due to stringifying and lack of possibility to import stuff.

Resolves #585, resolves #237
  • Loading branch information
rchl committed Feb 24, 2020
1 parent c85f816 commit c55bc6a
Show file tree
Hide file tree
Showing 8 changed files with 114 additions and 5 deletions.
15 changes: 14 additions & 1 deletion docs/options-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,20 @@ Here are all the options available when configuring the module and their default

```js
{
// vue-i18n configuration
// vue-i18n configuration.
// See documentation: http://kazupon.github.io/vue-i18n/api/#constructor-options
// To be able to pass more complex configuration options that can't be stringified, it's also
// supported to set this property to a path to a local configuration file. File needs to export
// a function (that will be passed a Nuxt context as a parameter) or plain object.
// Example path: '~/plugins/vue-i18n.js'
// Example file content:
// export default context => {
// return {
// modifiers: {
// snakeCase: (str) => str.split(' ').join('-')
// }
// }
// }
vueI18n: {},

// If true, vue-i18n-loader is added to Nuxt's Webpack config
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@
"geckodriver": "1.19.1",
"jest": "25.1.0",
"jsdom": "16.2.0",
"messageformat": "^2.3.0",
"nuxt": "2.11.0",
"puppeteer-core": "2.1.1",
"selenium-webdriver": "4.0.0-alpha.5",
Expand Down
2 changes: 1 addition & 1 deletion src/plugins/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ export default async (context) => {
}

// Set instance options
app.i18n = new VueI18n(vueI18n)
app.i18n = new VueI18n(typeof vueI18n === 'function' ? vueI18n(context) : vueI18n)
app.i18n.locales = locales
app.i18n.defaultLocale = defaultLocale
app.i18n.differentDomains = differentDomains
Expand Down
10 changes: 8 additions & 2 deletions src/templates/options.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,12 @@ function stringifyValue(value) {
}

for (const [key, value] of Object.entries(options)) {
if (key === 'vueI18n' && typeof value === 'string') {
%>export const <%= key %> = require('<%= value %>').default
<%
} else {
%>export const <%= key %> = <%= stringifyValue(value) %>
<%
}
}
%>
export const <%= key %> = <%= stringifyValue(value) %>
<% } %>
39 changes: 39 additions & 0 deletions test/fixture/basic/plugins/vue-i18n.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import MessageFormat from 'messageformat'

class CustomFormatter {
constructor (context) {
this._context = context
this._formatter = new MessageFormat(['en', 'fr'])
this._caches = Object.create(null)
}

interpolate (message, values) {
let fn = this._caches[message]
if (!fn) {
fn = this._formatter.compile(message.toUpperCase(), this._context.app.i18n.locale)
this._caches[message] = fn
}
return [fn(values)]
}
}

export default context => {
const formatter = new CustomFormatter(context)

return {
formatter,
messages: {
fr: {
home: 'Accueil',
about: 'À propos',
posts: 'Articles'
},
en: {
home: 'Homepage',
about: 'About us',
posts: 'Posts'
}
},
fallbackLocale: 'en'
}
}
24 changes: 24 additions & 0 deletions test/module.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -825,6 +825,30 @@ describe('differentDomains enabled', () => {
})
})

describe('external vue-i18n configuration', () => {
let nuxt

beforeAll(async () => {
const override = {
i18n: {
vueI18n: '~/plugins/vue-i18n.js'
}
}

nuxt = (await setup(loadConfig(__dirname, 'basic', override, { merge: true }))).nuxt
})

afterAll(async () => {
await nuxt.close()
})

test('uses custom message formatter', async () => {
const html = await get('/')
const dom = getDom(html)
expect(dom.querySelector('#current-page').textContent).toBe('page: HOMEPAGE')
})
})

describe('parsePages disabled', () => {
let nuxt

Expand Down
2 changes: 1 addition & 1 deletion types/nuxt-i18n.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ declare namespace NuxtVueI18n {
routesNameSeparator?: string
seo?: boolean
strategy?: 'no_prefix' | 'prefix_except_default' | 'prefix' | 'prefix_and_default'
vueI18n?: VueI18n.I18nOptions
vueI18n?: VueI18n.I18nOptions | string
vuex?: VuexInterface | false
}
}
Expand Down
26 changes: 26 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -8028,6 +8028,13 @@ make-dir@^3.0.0:
dependencies:
semver "^6.0.0"

make-plural@^4.3.0:
version "4.3.0"
resolved "https://registry.yarnpkg.com/make-plural/-/make-plural-4.3.0.tgz#f23de08efdb0cac2e0c9ba9f315b0dff6b4c2735"
integrity sha512-xTYd4JVHpSCW+aqDof6w/MebaMVNTVYBZhbB/vi513xXdiPT92JMVCo0Jq8W2UZnzYRFeVbQiQ+I25l13JuKvA==
optionalDependencies:
minimist "^1.2.0"

makeerror@1.0.x:
version "1.0.11"
resolved "https://registry.yarnpkg.com/makeerror/-/makeerror-1.0.11.tgz#e01a5c9109f2af79660e4e8b9587790184f5a96c"
Expand Down Expand Up @@ -8224,6 +8231,25 @@ merge2@^1.2.3, merge2@^1.3.0:
resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.3.0.tgz#5b366ee83b2f1582c48f87e47cf1a9352103ca81"
integrity sha512-2j4DAdlBOkiSZIsaXk4mTE3sRS02yBHAtfy127xRV3bQUFqXkjHCHLW6Scv7DwNRbIWNHH8zpnz9zMaKXIdvYw==

messageformat-formatters@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/messageformat-formatters/-/messageformat-formatters-2.0.1.tgz#0492c1402a48775f751c9b17c0354e92be012b08"
integrity sha512-E/lQRXhtHwGuiQjI7qxkLp8AHbMD5r2217XNe/SREbBlSawe0lOqsFb7rflZJmlQFSULNLIqlcjjsCPlB3m3Mg==

messageformat-parser@^4.1.2:
version "4.1.2"
resolved "https://registry.yarnpkg.com/messageformat-parser/-/messageformat-parser-4.1.2.tgz#fd34ec39912a14868a1595eaeb742485ab8ab372"
integrity sha512-7dWuifeyldz7vhEuL96Kwq1fhZXBW+TUfbnHN4UCrCxoXQTYjHnR78eI66Gk9LaLLsAvzPNVJBaa66DRfFNaiA==

messageformat@^2.3.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/messageformat/-/messageformat-2.3.0.tgz#de263c49029d5eae65d7ee25e0754f57f425ad91"
integrity sha512-uTzvsv0lTeQxYI2y1NPa1lItL5VRI8Gb93Y2K2ue5gBPyrbJxfDi/EYWxh2PKv5yO42AJeeqblS9MJSh/IEk4w==
dependencies:
make-plural "^4.3.0"
messageformat-formatters "^2.0.1"
messageformat-parser "^4.1.2"

methods@~1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee"
Expand Down

0 comments on commit c55bc6a

Please sign in to comment.