Skip to content

Instantly share code, notes, and snippets.

@ayyash
Last active March 13, 2019 14:09
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 ayyash/8d91cc842bb144a45ebabb75c2df2346 to your computer and use it in GitHub Desktop.
Save ayyash/8d91cc842bb144a45ebabb75c2df2346 to your computer and use it in GitHub Desktop.
Angular Universal Internationalization
{
"$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"
}
}
}
}
}
}
}
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);
};
// 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 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;
}
});
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;
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