Last active
March 13, 2019 14:09
-
-
Save ayyash/8d91cc842bb144a45ebabb75c2df2346 to your computer and use it in GitHub Desktop.
Angular Universal Internationalization
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"$schema": "./node_modules/@angular-devkit/core/src/workspace/workspace-schema.json", | |
"version": 1, | |
"newProjectRoot": "projects", | |
"projects": { | |
"projweb": { | |
"root": "", | |
"sourceRoot": "src", | |
"projectType": "application", | |
"prefix": "jr", | |
"architect": { | |
// ... | |
"server": { | |
"builder": "@angular-devkit/build-angular:server", | |
"options": { | |
"outputPath": "dist/en", | |
"main": "src/main.server.ts", | |
"tsConfig": "src/tsconfig.server.json" | |
}, | |
"configurations": { | |
"prod": { | |
"fileReplacements": [ | |
{ | |
"replace": "src/environments/environment.ts", | |
"with": "src/environments/environment.mockup.ts" | |
} | |
], | |
"optimization": true, | |
"sourceMap": false, | |
"namedChunks": true, | |
"extractLicenses": true, | |
"vendorChunk": true, | |
"deleteOutputPath": true, | |
"showCircularDependencies": false | |
}, | |
"prodAr": { | |
"outputPath": "dist/ar", | |
"fileReplacements": [ | |
{ | |
"replace": "src/environments/environment.ts", | |
"with": "src/environments/environment.mockup.ar.ts" | |
}, | |
{ | |
"replace": "src/locale/resources.ts", | |
"with": "src/locale/resources.ar.ts" | |
} | |
], | |
"optimization": true, | |
"sourceMap": false, | |
"namedChunks": true, | |
"extractLicenses": true, | |
"vendorChunk": true, | |
"deleteOutputPath": true, | |
"showCircularDependencies": false, | |
"i18nFile": "src/locale/messages.ar.xlf", | |
"i18nFormat": "xlf", | |
"i18nLocale": "ar", | |
"i18nMissingTranslation": "warning" | |
} | |
} | |
} | |
} | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const express = require('express'); | |
const en = require('./en'); | |
const ar = require('./ar'); | |
module.exports = function(app) { | |
const router = express.Router(); | |
router.use('/en', en.app); | |
// you can place / instead of /en to make english the default | |
router.use('/ar', ar.app); | |
app.use(router); | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// workaround for https://github.com/angular/angular-cli/issues/9975 | |
const arlocal = require('@angular/common/locales/ar').default; | |
registerLocaleData(arlocal, 'ar'); | |
// end workaround | |
// These are important and needed before anything else | |
import 'zone.js/dist/zone-node'; | |
import 'reflect-metadata'; | |
import { enableProdMode } from '@angular/core'; | |
import * as express from 'express'; | |
import { join } from 'path'; | |
// Faster server renders w/ Prod mode (dev mode never needed) | |
enableProdMode(); | |
// Express server | |
const app = express(); | |
// * NOTE :: leave this as require() since this file is built Dynamically from webpack | |
const { AppServerModuleNgFactory, LAZY_MODULE_MAP } = require('./dist/ar/main'); | |
// Express Engine | |
import { ngExpressEngine } from '@nguniversal/express-engine'; | |
// Import module map for lazy loading | |
import { provideModuleMap } from '@nguniversal/module-map-ngfactory-loader'; | |
import { registerLocaleData } from '@angular/common'; | |
app.engine( | |
'html', | |
ngExpressEngine({ | |
bootstrap: AppServerModuleNgFactory, | |
providers: [provideModuleMap(LAZY_MODULE_MAP)] | |
}) | |
); | |
app.set('view engine', 'html'); | |
app.set('views', join(process.cwd(), 'ar')); | |
// Server static files from /browser, or in my case /ar | |
app.get('*.*', express.static(join(process.cwd(), 'ar'))); | |
// All regular routes use the Universal engine | |
app.get('*', (req, res) => { | |
res.render('index', { req }); | |
}); | |
exports.app = app; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// this is the main server that servers either en or ar, this is done with pure nodejs, no typescript needed as it sits on its own | |
var express = require('express'); | |
// fix http | |
global.WebSocket = require('ws'); | |
global.XMLHttpRequest = require('xhr2'); | |
// fix window whenever used | |
global.window = undefined; | |
// fix localstroage | |
global.localStorage = { | |
getObject: function (key) { | |
return null; | |
}, | |
setObject: function (key, value, expiresin) { | |
if (expiresin === void 0) { expiresin = 0; } | |
} | |
}; | |
// and fix anything else used here | |
global._debug = function (o, message, type) { | |
if (type === 'e') { | |
console.log(message, o); | |
} | |
}; | |
/******* EXPRESS *******/ | |
var app = express(); | |
// here is what matters when it comes to serving angular languages | |
require('./server/routes')(app); | |
// catch 404 and forward to error handler | |
app.use(function(req, res, next) { | |
var err = new Error('404'); | |
err['statusCode'] = 404; | |
next(); | |
}); | |
app.use(function(err, req, res, next) { | |
res.status(err.status || 500); | |
console.log(err.stack); | |
err.internalMessage = err.message; | |
res.send(err); | |
}); | |
/*************** listening ***************/ | |
var port = process.env.PORT || 50010; | |
var server = app.listen(port, function(err) { | |
// console.log('started to listen to port: ' +port); | |
if (err) { | |
console.log(err); | |
return; | |
} | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import 'zone.js/dist/zone-node'; | |
import 'reflect-metadata'; | |
import { enableProdMode } from '@angular/core'; | |
import * as express from 'express'; | |
import { join } from 'path'; | |
// Faster server renders w/ Prod mode (dev mode never needed) | |
enableProdMode(); | |
// Express server | |
const app = express(); | |
// * NOTE :: leave this as require() since this file is built Dynamically from webpack | |
const { AppServerModuleNgFactory, LAZY_MODULE_MAP } = require('./dist/en/main'); | |
// Express Engine | |
import { ngExpressEngine } from '@nguniversal/express-engine'; | |
// Import module map for lazy loading | |
import { provideModuleMap } from '@nguniversal/module-map-ngfactory-loader'; | |
app.engine( | |
'html', | |
ngExpressEngine({ | |
bootstrap: AppServerModuleNgFactory, | |
providers: [provideModuleMap(LAZY_MODULE_MAP)] | |
}) | |
); | |
app.set('view engine', 'html'); | |
app.set('views', join(process.cwd(), 'en')); | |
// Server static files from /browser or in my case en | |
app.get('*.*', express.static(join(process.cwd(), 'en'))); | |
// All regular routes use the Universal engine | |
app.get('*', (req, res) => { | |
res.render('index', { req }); | |
}); | |
exports.app = app; | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const path = require('path'); | |
const webpack = require('webpack'); | |
// this packs server.ts which uses dist/en/main.js to create (dist/server/en.js and dist/server/ar.js) | |
module.exports = { | |
mode: 'none', | |
entry: { en: './server.ts', ar: './server.ar.ts' }, | |
resolve: { extensions: ['.js', '.ts'] }, | |
target: 'node', | |
// this makes sure we include node_modules and other 3rd party libraries | |
externals: [/(node_modules|main\..*\.js)/], | |
output: { | |
path: path.join(__dirname, 'dist/server'), // you could output to an external folder to keep things seperate | |
filename: '[name].js' | |
}, | |
module: { | |
rules: [{ test: /\.ts$/, loader: 'ts-loader' }] | |
}, | |
plugins: [ | |
// Temporary Fix for issue: https://github.com/angular/angular/issues/11580 | |
// for "WARNING Critical dependency: the request of a dependency is an expression" | |
new webpack.ContextReplacementPlugin( | |
/(.+)?angular(\\|\/)core(.+)?/, | |
path.join(__dirname, 'src'), // location of your src | |
{} // a map of your routes | |
), | |
// workaround for https://github.com/angular/angular-cli/issues/9975 | |
new webpack.ContextReplacementPlugin( | |
/(.+)?angular(\\|\/)common(\\|\/)locales/, | |
/(ar)$/ | |
) | |
] | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment