Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

i18n hashes invalidation #2464

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
"analyze": "webpack-bundle-analyzer dist/browser/stats.json",
"build": "ng build --configuration development",
"build:stats": "ng build --stats-json",
"build:prod": "yarn run build:ssr",
"build:prod": "cross-env NODE_ENV=production yarn run build:ssr",
"build:ssr": "ng build --configuration production && ng run dspace-angular:server:production",
"test": "ng test --source-map=true --watch=false --configuration test",
"test:watch": "nodemon --exec \"ng test --source-map=true --watch=true --configuration test\"",
Expand Down
4 changes: 3 additions & 1 deletion src/ngx-translate-loaders/translate-browser.loader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { NGX_TRANSLATE_STATE, NgxTranslateState } from './ngx-translate-state';
import { hasValue } from '../app/shared/empty.util';
import { map } from 'rxjs/operators';
import { of as observableOf, Observable } from 'rxjs';
import { environment } from '../environments/environment';

/**
* A TranslateLoader for ngx-translate to retrieve i18n messages from the TransferState, or download
Expand Down Expand Up @@ -33,9 +34,10 @@ export class TranslateBrowserLoader implements TranslateLoader {
if (hasValue(messages)) {
return observableOf(messages);
} else {
const translationHash: string = environment.production ? `.${(process.env.languageHashes as any)[lang + '.json5']}` : '';
// If they're not available on the transfer state (e.g. when running in dev mode), retrieve
// them using HttpClient
return this.http.get('' + this.prefix + lang + this.suffix, { responseType: 'text' }).pipe(
return this.http.get(`${this.prefix}${lang}${translationHash}${this.suffix}`, { responseType: 'text' }).pipe(
map((json: any) => JSON.parse(json))
);
}
Expand Down
3 changes: 2 additions & 1 deletion src/ngx-translate-loaders/translate-server.loader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,9 @@ export class TranslateServerLoader implements TranslateLoader {
* @param lang the language code
*/
public getTranslation(lang: string): Observable<any> {
const translationHash: string = (process.env.languageHashes as any)[lang + '.json5'];
// Retrieve the file for the given language, and parse it
const messages = JSON.parse(readFileSync(`${this.prefix}${lang}${this.suffix}`, 'utf8'));
const messages = JSON.parse(readFileSync(`${this.prefix}${lang}.${translationHash}${this.suffix}`, 'utf8'));
// Store the parsed messages in the transfer state so they'll be available immediately when the
// app loads on the client
this.storeInTransferState(lang, messages);
Expand Down
47 changes: 39 additions & 8 deletions webpack/helpers.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,49 @@
const path = require('path');
import { readFileSync, readdirSync, statSync, Stats } from 'fs';
import { join, resolve } from 'path';

const md5 = require('md5');

export const projectRoot = (relativePath) => {
return path.resolve(__dirname, '..', relativePath);
return resolve(__dirname, '..', relativePath);
};

export const globalCSSImports = () => {
return [
projectRoot(path.join('src', 'styles', '_variables.scss')),
projectRoot(path.join('src', 'styles', '_mixins.scss')),
projectRoot(join('src', 'styles', '_variables.scss')),
projectRoot(join('src', 'styles', '_mixins.scss')),
];
};

/**
* Calculates the md5 hash of a file
*
* @param filePath The path of the file
*/
export function calculateFileHash(filePath: string): string {
const fileContent: Buffer = readFileSync(filePath);
return md5(fileContent);
}

module.exports = {
projectRoot,
globalCSSImports
};
/**
* Calculate the hashes of all the files (matching the given regex) in a certain folder
*
* @param folderPath The path of the folder
* @param regExp A regex of the files in the folder for which a hash needs to be generated
*/
export function getFileHashes(folderPath: string, regExp: RegExp): { [fileName: string]: string } {
const files: string[] = readdirSync(folderPath);
let hashes: { [fileName: string]: string } = {};

for (const file of files) {
if (file.match(regExp)) {
const filePath: string = join(folderPath, file);
const stats: Stats = statSync(filePath);

if (stats.isFile()) {
hashes[file] = calculateFileHash(filePath);
}
}
}

return hashes;
}
11 changes: 8 additions & 3 deletions webpack/webpack.common.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { globalCSSImports, projectRoot } from './helpers';
import { globalCSSImports, projectRoot, getFileHashes, calculateFileHash } from './helpers';
import { EnvironmentPlugin } from 'webpack';

const CopyWebpackPlugin = require('copy-webpack-plugin');
const path = require('path');
Expand All @@ -18,12 +19,13 @@ export const copyWebpackOptions = {
// use [\/|\\] to match both POSIX and Windows separators
const matches = absoluteFilename.match(/.*[\/|\\]assets[\/|\\](.+)\.json5$/);
if (matches) {
const fileHash: string = process.env.NODE_ENV === 'production' ? `.${calculateFileHash(absoluteFilename)}` : '';
// matches[1] is the relative path from src/assets to the JSON5 file, without the extension
return path.join('assets', matches[1] + '.json');
return path.join('assets', `${matches[1]}${fileHash}.json`);
}
},
transform(content) {
return JSON.stringify(JSON5.parse(content.toString()))
return JSON.stringify(JSON5.parse(content.toString()));
}
},
{
Expand Down Expand Up @@ -77,6 +79,9 @@ const SCSS_LOADERS = [

export const commonExports = {
plugins: [
new EnvironmentPlugin({
languageHashes: getFileHashes(path.join(__dirname, '..', 'src', 'assets', 'i18n'), /.*\.json5/g),
}),
new CopyWebpackPlugin(copyWebpackOptions),
],
module: {
Expand Down
Loading