Skip to content

Commit

Permalink
Merge pull request #15 from companieshouse/tferns-IDVA6-1468-refactor
Browse files Browse the repository at this point in the history
IDVA6-1468: Refactor i18n localization to support both project and node_modules locales
  • Loading branch information
tferns-ch authored Sep 11, 2024
2 parents efb6cda + 6358195 commit a4e8f2a
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 47 deletions.
2 changes: 0 additions & 2 deletions src/middleware/manageLocales.middleware.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,8 @@ import { QUERY_PAR_LANG } from "../constants/constants"
import LocalesService from "../services/locales/locales.service"
import LanguageNames from "../utils/languageNames"
import log from "../utils/log";
import { copyLocales } from "../utils/locales";

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

log("---------- LocalesMiddleware ------------")
Expand Down
63 changes: 42 additions & 21 deletions src/utils/i18nCh.ts
Original file line number Diff line number Diff line change
@@ -1,47 +1,49 @@
import i18next from "i18next"
import Backend from "i18next-fs-backend"
import path from "path";
import path from "path";
import fs, { readdirSync, lstatSync } from "fs"
import log from "./log";
import { NODE_MODULES_LOCALES_PATH } from "../constants/constants";

export default class i18nCh {

private static instance: i18nCh
private i18nInst
private localesFolder
private nodeModulesFolder
private nameSpaces: string[] = [];

//_______________________________________________________________________________________________
private constructor(localesFolder = "", nameSpaces: string[] = [], lang = "en") {
try {
if (!localesFolder) {
// no point to translate these errors as if they should ever happen they are input for devs, not customers
throw new Error("i18nCh initialization error: path to locales must be provided")
}
this.localesFolder = localesFolder
if ( nameSpaces.length === 0) {
nameSpaces = this.loadAllNamespaces();
this.nodeModulesFolder = NODE_MODULES_LOCALES_PATH

if (nameSpaces.length === 0) {
nameSpaces = this.loadAllNamespaces();
}
this.nameSpaces = nameSpaces

this.i18nInst = i18next
this.i18nInst
.use(Backend)
.init({
.use(Backend)
.init({
initImmediate: false, // false = will load the resources synchronously
ns: nameSpaces,
partialBundledLanguages: true,
lng: lang,
fallbackLng: "en",
preload: readdirSync(localesFolder).filter((fileName) => {
const joinedPath = path.join(localesFolder, fileName)
return lstatSync(joinedPath).isDirectory()
}),
preload: this.getLanguageFolders(),
backend: {
loadPath: path.join(localesFolder, `{{lng}}/{{ns}}.json`)
loadPath: (lng: string, ns: string) => {
const projectPath = path.join(this.localesFolder, `${lng}/${ns}.json`);
const nodePath = path.join(this.nodeModulesFolder, `${lng}/${ns}.json`);
return fs.existsSync(projectPath) ? projectPath : nodePath;
}
}
})
})
}
catch (err) {
throw err; // propagate
Expand All @@ -59,17 +61,16 @@ export default class i18nCh {
//_______________________________________________________________________________________________
// load all the file names (without extension: ".json") present in 'localesFolder'
private loadAllNamespaces(): string[] {
if (!this.localesFolder) {
return [];
}
const allNamespaces = [
this.loadNamespacesFromFolder(this.localesFolder),
this.loadNamespacesFromFolder(this.nodeModulesFolder)
];

const projectRootNamespaces = this.loadNamespacesFromPath(path.join(this.localesFolder, "en"));
const nodeModulesNamespaces = this.loadNamespacesFromPath(path.join(NODE_MODULES_LOCALES_PATH, "en"));

return [...new Set([...projectRootNamespaces, ...nodeModulesNamespaces])];
return [...new Set(allNamespaces.flat())];
}

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

private getLanguageFolders(): string[] {
const allFolders = [
this.getFoldersFromPath(this.localesFolder),
this.getFoldersFromPath(this.nodeModulesFolder)
];
return [...new Set(allFolders.flat())];
}

private getFoldersFromPath(folderPath: string): string[] {
try {
return readdirSync(folderPath).filter((fileName) => {
const joinedPath = path.join(folderPath, fileName)
return lstatSync(joinedPath).isDirectory()
});
} catch (error) {
log(`Error reading language folders from ${folderPath}: ${error}`);
return [];
}
}

//_______________________________________________________________________________________________
// change to another lang
private changeLanguage (lang: string) {
Expand Down
24 changes: 0 additions & 24 deletions src/utils/locales.ts

This file was deleted.

0 comments on commit a4e8f2a

Please sign in to comment.