rsnext/examples/with-react-intl/server.js
Matthew Lilley cefbb84230 Fix for locale.split is not a function. (#5794)
* Fix for locale.split is not a function.

Following from https://github.com/zeit/next.js/pull/5488

- Renamed languages to supportedLanguages
- Firstly, accept languages based on supportedLanguages
- And finally, accept a single language, if it returns false, the default of 'en' is used.

I looked at the navigator library, which is used by 'accept', this should be a more solid solution, since we can now know that `const locale` is always a string.

// Before (Sometimes returns an array as `const local`)
const locale = accept.language(languages) || 'en' 

// After (Always returns a string)
const locale = accept.language(accept.languages(supportedLanguages)) || 'en';

* Update server.js

Update variable name.
2018-12-03 09:10:31 -08:00

54 lines
2 KiB
JavaScript

// Polyfill Node with `Intl` that has data for all locales.
// See: https://formatjs.io/guides/runtime-environments/#server
const IntlPolyfill = require('intl')
Intl.NumberFormat = IntlPolyfill.NumberFormat
Intl.DateTimeFormat = IntlPolyfill.DateTimeFormat
const {readFileSync} = require('fs')
const {basename} = require('path')
const {createServer} = require('http')
const accepts = require('accepts')
const glob = require('glob')
const next = require('next')
const port = parseInt(process.env.PORT, 10) || 3000
const dev = process.env.NODE_ENV !== 'production'
const app = next({dev})
const handle = app.getRequestHandler()
// Get the supported languages by looking for translations in the `lang/` dir.
const supportedLanguages = glob.sync('./lang/*.json').map((f) => basename(f, '.json'))
// We need to expose React Intl's locale data on the request for the user's
// locale. This function will also cache the scripts by lang in memory.
const localeDataCache = new Map()
const getLocaleDataScript = (locale) => {
const lang = locale.split('-')[0]
if (!localeDataCache.has(lang)) {
const localeDataFile = require.resolve(`react-intl/locale-data/${lang}`)
const localeDataScript = readFileSync(localeDataFile, 'utf8')
localeDataCache.set(lang, localeDataScript)
}
return localeDataCache.get(lang)
}
// We need to load and expose the translations on the request for the user's
// locale. These will only be used in production, in dev the `defaultMessage` in
// each message description in the source code will be used.
const getMessages = (locale) => {
return require(`./lang/${locale}.json`)
}
app.prepare().then(() => {
createServer((req, res) => {
const accept = accepts(req)
const locale = accept.language(accept.languages(supportedLanguages)) || 'en'
req.locale = locale
req.localeDataScript = getLocaleDataScript(locale)
req.messages = dev ? {} : getMessages(locale)
handle(req, res)
}).listen(port, (err) => {
if (err) throw err
console.log(`> Ready on http://localhost:${port}`)
})
})