Skip to content

Commit a4e8f2a

Browse files
authored
Merge pull request #15 from companieshouse/tferns-IDVA6-1468-refactor
IDVA6-1468: Refactor i18n localization to support both project and node_modules locales
2 parents efb6cda + 6358195 commit a4e8f2a

File tree

3 files changed

+42
-47
lines changed

3 files changed

+42
-47
lines changed

src/middleware/manageLocales.middleware.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,8 @@ import { QUERY_PAR_LANG } from "../constants/constants"
33
import LocalesService from "../services/locales/locales.service"
44
import LanguageNames from "../utils/languageNames"
55
import log from "../utils/log";
6-
import { copyLocales } from "../utils/locales";
76

87
export function LocalesMiddleware(): RequestHandler {
9-
copyLocales();
108
return (req: Request, res: Response, next: NextFunction) => {
119

1210
log("---------- LocalesMiddleware ------------")

src/utils/i18nCh.ts

Lines changed: 42 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,49 @@
11
import i18next from "i18next"
22
import Backend from "i18next-fs-backend"
3-
import path from "path";
3+
import path from "path";
44
import fs, { readdirSync, lstatSync } from "fs"
55
import log from "./log";
66
import { NODE_MODULES_LOCALES_PATH } from "../constants/constants";
77

88
export default class i18nCh {
9-
109
private static instance: i18nCh
1110
private i18nInst
1211
private localesFolder
12+
private nodeModulesFolder
1313
private nameSpaces: string[] = [];
1414

15-
//_______________________________________________________________________________________________
1615
private constructor(localesFolder = "", nameSpaces: string[] = [], lang = "en") {
1716
try {
1817
if (!localesFolder) {
1918
// no point to translate these errors as if they should ever happen they are input for devs, not customers
2019
throw new Error("i18nCh initialization error: path to locales must be provided")
2120
}
2221
this.localesFolder = localesFolder
23-
if ( nameSpaces.length === 0) {
24-
nameSpaces = this.loadAllNamespaces();
22+
this.nodeModulesFolder = NODE_MODULES_LOCALES_PATH
23+
24+
if (nameSpaces.length === 0) {
25+
nameSpaces = this.loadAllNamespaces();
2526
}
2627
this.nameSpaces = nameSpaces
2728

2829
this.i18nInst = i18next
2930
this.i18nInst
30-
.use(Backend)
31-
.init({
31+
.use(Backend)
32+
.init({
3233
initImmediate: false, // false = will load the resources synchronously
3334
ns: nameSpaces,
3435
partialBundledLanguages: true,
3536
lng: lang,
3637
fallbackLng: "en",
37-
preload: readdirSync(localesFolder).filter((fileName) => {
38-
const joinedPath = path.join(localesFolder, fileName)
39-
return lstatSync(joinedPath).isDirectory()
40-
}),
38+
preload: this.getLanguageFolders(),
4139
backend: {
42-
loadPath: path.join(localesFolder, `{{lng}}/{{ns}}.json`)
40+
loadPath: (lng: string, ns: string) => {
41+
const projectPath = path.join(this.localesFolder, `${lng}/${ns}.json`);
42+
const nodePath = path.join(this.nodeModulesFolder, `${lng}/${ns}.json`);
43+
return fs.existsSync(projectPath) ? projectPath : nodePath;
44+
}
4345
}
44-
})
46+
})
4547
}
4648
catch (err) {
4749
throw err; // propagate
@@ -59,17 +61,16 @@ export default class i18nCh {
5961
//_______________________________________________________________________________________________
6062
// load all the file names (without extension: ".json") present in 'localesFolder'
6163
private loadAllNamespaces(): string[] {
62-
if (!this.localesFolder) {
63-
return [];
64-
}
64+
const allNamespaces = [
65+
this.loadNamespacesFromFolder(this.localesFolder),
66+
this.loadNamespacesFromFolder(this.nodeModulesFolder)
67+
];
6568

66-
const projectRootNamespaces = this.loadNamespacesFromPath(path.join(this.localesFolder, "en"));
67-
const nodeModulesNamespaces = this.loadNamespacesFromPath(path.join(NODE_MODULES_LOCALES_PATH, "en"));
68-
69-
return [...new Set([...projectRootNamespaces, ...nodeModulesNamespaces])];
69+
return [...new Set(allNamespaces.flat())];
7070
}
7171

72-
private loadNamespacesFromPath(folderPath: string): string[] {
72+
private loadNamespacesFromFolder(baseFolder: string): string[] {
73+
const folderPath = path.join(baseFolder, "en");
7374
try {
7475
return fs.readdirSync(folderPath)
7576
.filter(file => path.extname(file) === ".json")
@@ -80,6 +81,26 @@ export default class i18nCh {
8081
}
8182
}
8283

84+
private getLanguageFolders(): string[] {
85+
const allFolders = [
86+
this.getFoldersFromPath(this.localesFolder),
87+
this.getFoldersFromPath(this.nodeModulesFolder)
88+
];
89+
return [...new Set(allFolders.flat())];
90+
}
91+
92+
private getFoldersFromPath(folderPath: string): string[] {
93+
try {
94+
return readdirSync(folderPath).filter((fileName) => {
95+
const joinedPath = path.join(folderPath, fileName)
96+
return lstatSync(joinedPath).isDirectory()
97+
});
98+
} catch (error) {
99+
log(`Error reading language folders from ${folderPath}: ${error}`);
100+
return [];
101+
}
102+
}
103+
83104
//_______________________________________________________________________________________________
84105
// change to another lang
85106
private changeLanguage (lang: string) {

src/utils/locales.ts

Lines changed: 0 additions & 24 deletions
This file was deleted.

0 commit comments

Comments
 (0)