Skip to content

Instantly share code, notes, and snippets.

@gregbown
Last active December 27, 2019 21:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gregbown/1b02096766606b6d80703a6c416c1ea5 to your computer and use it in GitHub Desktop.
Save gregbown/1b02096766606b6d80703a6c416c1ea5 to your computer and use it in GitHub Desktop.
i18next server AND client side setup with express
/* Note: Just enough to get the idea here.
resources/
|- locales/
|- en/
|- translation.json
|- zh/
|- translation.json
|- static/
|- css/
|- fonts/
|- img/
|- js/
|- libs/
main.js
favicon.ico
|- templates/
|- includes/
|- pages
server/
|- app/
|- controllers/
root.js
|- middlewares/
|- routes/
package.json
*/
/* Server side i18next setup */
i18next
.use(i18nextBackend)
.use(i18nextMiddleware.LanguageDetector)
.init({
backend: {
/* Server side uses root directory */
loadPath: process.cwd() + '/resources/locales/{{lng}}/{{ns}}.json'
},
fallbackLng: 'en',
preload: ['en', 'zh'],
saveMissing: true,
detection: {
// order and from where user language should be detected
order: ['session', 'querystring', 'cookie', 'header'],
lookupQuerystring: 'locale',
lookupCookie: 'locale',
lookupHeader: 'accept-language',
lookupSession: 'locale',
lookupFromPathIndex: 0,
caches: false,
cookieExpirationDate: new Date(Date.now() + settings.server.cookieTTL),
cookieDomain: 'local.eazact.com',
cookieSecure: false, // if need secure cookie, requires ssl
}
});
/* before routes
* Define view rendering engine */
app.set('view engine', 'ejs');
app.set('views', 'resources/templates'); // <= path from root
app.use(i18nextMiddleware.handle(i18next));
/* Define static assets */
app.use(express.static('resources/static'));
/* map locales to a /json directory for client */
app.use('/json', express.static('resources/locales'));
/* map JavaScript to libs directory */
app.use('/js/libs', express.static(path.join(process.cwd(), 'node_modules/jquery/dist'), { maxAge: 31557600000 }));
app.use('/js/libs', express.static(path.join(process.cwd(), 'node_modules/popper.js/dist/umd'), { maxAge: 31557600000 }));
app.use('/js/libs', express.static(path.join(process.cwd(), 'node_modules/bootstrap/dist/js'), { maxAge: 31557600000 }));
/* client side i18next script dependencies */
app.use('/js/libs', express.static(path.join(process.cwd(), 'node_modules/i18next/dist/umd'), { maxAge: 31557600000 }));
app.use('/js/libs', express.static(path.join(process.cwd(), 'node_modules/i18next-xhr-backend/dist/umd'), { maxAge: 31557600000 }));
app.use('/js/libs', express.static(path.join(process.cwd(), 'node_modules/i18next-browser-languagedetector/dist/umd'), { maxAge: 31557600000 }));
app.use('/fonts', express.static(path.join(process.cwd(), 'node_modules/font-awesome/fonts'), { maxAge: 31557600000 }));
/** I18N client side setup */
const i18n = window.i18next || {};
const backend = window.i18nextXHRBackend || {};
const detector = window.i18nextBrowserLanguageDetector || {};
const i18nOptions = {
debug: true, // remove for production
fallbackLng: 'en',
preload: ['en', 'zh'],
load: 'languageOnly', // Prevents backend from trying to load ./en-US/...
ns: 'translation',
detectLanguage: true,
detection: {order: ['cookie', 'querystring'], lookupCookie: 'locale', lookupQuerystring: 'locale', caches: false},
defaultNS: 'translation', // The name of your JSON file
backend: {loadPath: '/json/{{lng}}/{{ns}}.json'},
getAsync: false
};
i18n.use(detector).use(backend).init(i18nOptions).then(function(result) {
console.log('Translated value = ' + i18n.t('title.account'));
});
<script src='/js/libs/jquery.min.js' type='text/javascript'></script>
<script src='/js/libs/popper.min.js' type='text/javascript'></script>
<script src='/js/libs/bootstrap.min.js' type='text/javascript'></script>
<!-- i18next client side dependencies -->
<script src='/js/libs/i18next.min.js' type='text/javascript'></script>
<script src='/js/libs/i18nextXHRBackend.min.js' type='text/javascript'></script>
<script src='/js/libs/i18nextBrowserLanguageDetector.js' type='text/javascript'></script>
<script src='/js/libs/main.js' type='text/javascript'></script>
</body>
</html>
<h1><%= t('title.account') %></h1>
/**
* @method
* @name setLocale
* @description ajax handler for client setting locale
* @function set locale cookie
* @memberOf RootController
*
* @param req {object} The Request object represents the HTTP <a href="https://expressjs.com/en/api.html#req">request</a>
* and has properties for the request query string, parameters, body, HTTP headers, and so on.
*
* @param res {object} The Response object represents the HTTP <a href="https://expressjs.com/en/api.html#res">response</a>
* that an Express app sends when it gets an HTTP request.
*/
function setLocale(req, res) {
if (req.body.locale) {
res.cookie('locale', req.body.locale, { expires: new Date(Date.now() + settings.server.cookieTTL), httpOnly: false });
return res.status(200).send({result: 'Success', value: req.body.locale});
}
}
{
"title": {
"account": "帳戶 主頁",
"login": "登錄",
"signup": "註冊"
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment