added "getInstanceForLocale(userLocale)" into I18nManager class
modified all the calls to "new I18nManager()"
MODIFY
src/integration/billing/stripe/StripeBillingIntegration.ts
src/integration/billing/stripe/StripeBillingIntegration.ts
@@ -453,7 +453,7 @@ export default class StripeBillingIntegration extends BillingIntegration<StripeB
const chargeBox = transaction.chargeBox;
// Create or update invoice in Stripe
let description = '';
- const i18nManager = new I18nManager(transaction.user.locale);
+ const i18nManager = I18nManager.getInstanceForLocale(transaction.user.locale);
const totalConsumptionkWh = Math.round(transaction.stop.totalConsumptionWh / 100) / 10;
const time = i18nManager.formatDateTime(transaction.stop.timestamp, 'LTS');
if (chargeBox && chargeBox.siteArea && chargeBox.siteArea.name) {
@@ -645,7 +645,7 @@ export default class StripeBillingIntegration extends BillingIntegration<StripeB
await this.checkConnection();
const fullName = Utils.buildUserFullName(user, false, false);
const locale = Utils.getLanguageFromLocale(user.locale).toLocaleLowerCase();
- const i18nManager = new I18nManager(user.locale);
+ const i18nManager = I18nManager.getInstanceForLocale(user.locale);
const description = i18nManager.translate('billing.generatedUser', { email: user.email });
let customer;
if (user.billingData && user.billingData.customerID) {

MODIFY
src/notification/remote-push-notification/RemotePushNotificationTask.ts
src/notification/remote-push-notification/RemotePushNotificationTask.ts
@@ -45,7 +45,7 @@ export default class RemotePushNotificationTask implements NotificationTask {
public async sendUserAccountInactivity(data: UserAccountInactivityNotification, user: User, tenant: Tenant, severity: NotificationSeverity): Promise<void> {
// Set the locale
- const i18nManager = new I18nManager(user.locale);
+ const i18nManager = I18nManager.getInstanceForLocale(user.locale);
// Get Message Text
const title = i18nManager.translate('notifications.userAccountInactivity.title');
const body = i18nManager.translate('notifications.userAccountInactivity.body',
@@ -60,7 +60,7 @@ export default class RemotePushNotificationTask implements NotificationTask {
public async sendPreparingSessionNotStarted(data: PreparingSessionNotStartedNotification, user: User, tenant: Tenant, severity: NotificationSeverity): Promise<void> {
// Set the locale
- const i18nManager = new I18nManager(user.locale);
+ const i18nManager = I18nManager.getInstanceForLocale(user.locale);
// Get Message Text
const title = i18nManager.translate('notifications.preparingSessionNotStarted.title');
const body = i18nManager.translate('notifications.preparingSessionNotStarted.body',
@@ -76,7 +76,7 @@ export default class RemotePushNotificationTask implements NotificationTask {
public async sendSessionNotStarted(data: SessionNotStartedNotification, user: User, tenant: Tenant, severity: NotificationSeverity): Promise<void> {
// Set the locale
- const i18nManager = new I18nManager(user.locale);
+ const i18nManager = I18nManager.getInstanceForLocale(user.locale);
// Get Message Text
const title = i18nManager.translate('notifications.sessionNotStarted.title');
const body = i18nManager.translate('notifications.sessionNotStarted.body',
@@ -91,7 +91,7 @@ export default class RemotePushNotificationTask implements NotificationTask {
public async sendOfflineChargingStations(data: OfflineChargingStationNotification, user: User, tenant: Tenant, severity: NotificationSeverity): Promise<void> {
// Set the locale
- const i18nManager = new I18nManager(user.locale);
+ const i18nManager = I18nManager.getInstanceForLocale(user.locale);
// Get Message Text
const title = i18nManager.translate('notifications.offlineChargingStation.title');
const body = i18nManager.translate('notifications.offlineChargingStation.body',
@@ -114,7 +114,7 @@ export default class RemotePushNotificationTask implements NotificationTask {
public async sendOptimalChargeReached(data: OptimalChargeReachedNotification, user: User, tenant: Tenant, severity: NotificationSeverity): Promise<void> {
// Set the locale
- const i18nManager = new I18nManager(user.locale);
+ const i18nManager = I18nManager.getInstanceForLocale(user.locale);
// Get Message Text
const title = i18nManager.translate('notifications.optimalChargeReached.title');
const body = i18nManager.translate('notifications.optimalChargeReached.body',
@@ -131,7 +131,7 @@ export default class RemotePushNotificationTask implements NotificationTask {
public async sendEndOfCharge(data: EndOfChargeNotification, user: User, tenant: Tenant, severity: NotificationSeverity): Promise<void> {
// Set the locale
- const i18nManager = new I18nManager(user.locale);
+ const i18nManager = I18nManager.getInstanceForLocale(user.locale);
// Get Message Text
const title = i18nManager.translate('notifications.endOfCharge.title');
const body = i18nManager.translate('notifications.endOfCharge.body',
@@ -148,7 +148,7 @@ export default class RemotePushNotificationTask implements NotificationTask {
public async sendEndOfSession(data: EndOfSessionNotification, user: User, tenant: Tenant, severity: NotificationSeverity): Promise<void> {
// Set the locale
- const i18nManager = new I18nManager(user.locale);
+ const i18nManager = I18nManager.getInstanceForLocale(user.locale);
// Get Message Text
const title = i18nManager.translate('notifications.endOfSession.title');
const body = i18nManager.translate('notifications.endOfSession.body',
@@ -175,7 +175,7 @@ export default class RemotePushNotificationTask implements NotificationTask {
public async sendEndUserErrorNotification(data: EndUserErrorNotification, user: User, tenant: Tenant, severity: NotificationSeverity): Promise<void> {
// Set the locale
- const i18nManager = new I18nManager(user.locale);
+ const i18nManager = I18nManager.getInstanceForLocale(user.locale);
// Get Message Text
const title = i18nManager.translate('notifications.endUserErrorNotification.title');
const body = i18nManager.translate('notifications.endUserErrorNotification.body',
@@ -188,7 +188,7 @@ export default class RemotePushNotificationTask implements NotificationTask {
public async sendChargingStationStatusError(data: ChargingStationStatusErrorNotification, user: User, tenant: Tenant, severity: NotificationSeverity): Promise<void> {
// Set the locale
- const i18nManager = new I18nManager(user.locale);
+ const i18nManager = I18nManager.getInstanceForLocale(user.locale);
// Get Message Text
const title = i18nManager.translate('notifications.chargingStationStatusError.title');
const body = i18nManager.translate('notifications.chargingStationStatusError.body',
@@ -204,7 +204,7 @@ export default class RemotePushNotificationTask implements NotificationTask {
public async sendChargingStationRegistered(data: ChargingStationRegisteredNotification, user: User, tenant: Tenant, severity: NotificationSeverity): Promise<void> {
// Set the locale
- const i18nManager = new I18nManager(user.locale);
+ const i18nManager = I18nManager.getInstanceForLocale(user.locale);
// Get Message Text
const title = i18nManager.translate('notifications.chargingStationRegistered.title');
const body = i18nManager.translate('notifications.chargingStationRegistered.body',
@@ -219,7 +219,7 @@ export default class RemotePushNotificationTask implements NotificationTask {
public async sendUserAccountStatusChanged(data: UserAccountStatusChangedNotification, user: User, tenant: Tenant, severity: NotificationSeverity): Promise<void> {
// Set the locale
- const i18nManager = new I18nManager(user.locale);
+ const i18nManager = I18nManager.getInstanceForLocale(user.locale);
const status = user.status === UserStatus.ACTIVE ?
i18nManager.translate('notifications.userAccountStatusChanged.activated') :
i18nManager.translate('notifications.userAccountStatusChanged.suspended');
@@ -238,7 +238,7 @@ export default class RemotePushNotificationTask implements NotificationTask {
public async sendUnknownUserBadged(data: UnknownUserBadgedNotification, user: User, tenant: Tenant, severity: NotificationSeverity): Promise<void> {
// Set the locale
- const i18nManager = new I18nManager(user.locale);
+ const i18nManager = I18nManager.getInstanceForLocale(user.locale);
// Get Message Text
const title = i18nManager.translate('notifications.unknownUserBadged.title');
const body = i18nManager.translate('notifications.unknownUserBadged.body',
@@ -254,7 +254,7 @@ export default class RemotePushNotificationTask implements NotificationTask {
public async sendSessionStarted(data: TransactionStartedNotification, user: User, tenant: Tenant, severity: NotificationSeverity): Promise<void> {
// Set the locale
- const i18nManager = new I18nManager(user.locale);
+ const i18nManager = I18nManager.getInstanceForLocale(user.locale);
// Get Message Text
const title = i18nManager.translate('notifications.sessionStarted.title');
const body = i18nManager.translate('notifications.sessionStarted.body',
@@ -276,7 +276,7 @@ export default class RemotePushNotificationTask implements NotificationTask {
public async sendSmtpAuthError(data: SmtpAuthErrorNotification, user: User, tenant: Tenant, severity: NotificationSeverity): Promise<void> {
// Set the locale
- const i18nManager = new I18nManager(user.locale);
+ const i18nManager = I18nManager.getInstanceForLocale(user.locale);
// Get Message Text
const title = i18nManager.translate('notifications.smtpAuthError.title');
const body = i18nManager.translate('notifications.smtpAuthError.body', { tenantName: tenant.name });
@@ -286,7 +286,7 @@ export default class RemotePushNotificationTask implements NotificationTask {
public async sendOCPIPatchChargingStationsStatusesError(data: OCPIPatchChargingStationsStatusesErrorNotification, user: User, tenant: Tenant, severity: NotificationSeverity): Promise<void> {
// Set the locale
- const i18nManager = new I18nManager(user.locale);
+ const i18nManager = I18nManager.getInstanceForLocale(user.locale);
// Get Message Text
const title = i18nManager.translate('notifications.ocpiPatchChargingStationsStatusesError.title');
const body = i18nManager.translate('notifications.ocpiPatchChargingStationsStatusesError.body',
@@ -297,7 +297,7 @@ export default class RemotePushNotificationTask implements NotificationTask {
public async sendBillingSynchronizationFailed(data: BillingUserSynchronizationFailedNotification, user: User, tenant: Tenant, severity: NotificationSeverity): Promise<void> {
// Set the locale
- const i18nManager = new I18nManager(user.locale);
+ const i18nManager = I18nManager.getInstanceForLocale(user.locale);
// Get Message Text
const title = i18nManager.translate('notifications.billingUserSynchronizationFailed.title');
const body = i18nManager.translate('notifications.billingUserSynchronizationFailed.body',
@@ -309,7 +309,7 @@ export default class RemotePushNotificationTask implements NotificationTask {
public async sendBillingInvoiceSynchronizationFailed(data: BillingInvoiceSynchronizationFailedNotification, user: User, tenant: Tenant, severity: NotificationSeverity): Promise<void> {
// Set the locale
- const i18nManager = new I18nManager(user.locale);
+ const i18nManager = I18nManager.getInstanceForLocale(user.locale);
// Get Message Text
const title = i18nManager.translate('notifications.billingInvoiceSynchronizationFailed.title');
const body = i18nManager.translate('notifications.billingInvoiceSynchronizationFailed.body',
@@ -321,7 +321,7 @@ export default class RemotePushNotificationTask implements NotificationTask {
public async sendComputeAndApplyChargingProfilesFailed(data: ComputeAndApplyChargingProfilesFailedNotification, user: User, tenant: Tenant, severity: NotificationSeverity): Promise<void> {
// Set the locale
- const i18nManager = new I18nManager(user.locale);
+ const i18nManager = I18nManager.getInstanceForLocale(user.locale);
// Get Message Text
const title = i18nManager.translate('notifications.computeAndApplyChargingProfilesFailed.title');
const body = i18nManager.translate('notifications.computeAndApplyChargingProfilesFailed.body',
@@ -334,7 +334,7 @@ export default class RemotePushNotificationTask implements NotificationTask {
public async sendBillingNewInvoice(data: BillingNewInvoiceNotification, user: User, tenant: Tenant, severity: NotificationSeverity): Promise<void> {
// Set the locale
- const i18nManager = new I18nManager(user.locale);
+ const i18nManager = I18nManager.getInstanceForLocale(user.locale);
// Get Message Text
const title = i18nManager.translate('notifications.billingNewInvoice.title');
const body = i18nManager.translate('notifications.billingNewInvoice.body',

MODIFY
src/server/ocpp/services/OCPPService.ts
src/server/ocpp/services/OCPPService.ts
@@ -1371,7 +1371,7 @@ export default class OCPPService {
private async notifyEndOfCharge(tenantID: string, chargingStation: ChargingStation, transaction: Transaction) {
if (transaction.user) {
// Get the i18n lib
- const i18nManager = new I18nManager(transaction.user.locale);
+ const i18nManager = I18nManager.getInstanceForLocale(transaction.user.locale);
const tenant = await TenantStorage.getTenant(tenantID);
// Notify (Async)
NotificationHandler.sendEndOfCharge(
@@ -1396,7 +1396,7 @@ export default class OCPPService {
private async notifyOptimalChargeReached(tenantID: string, chargingStation: ChargingStation, transaction: Transaction) {
if (transaction.user) {
// Get the i18n lib
- const i18nManager = new I18nManager(transaction.user.locale);
+ const i18nManager = I18nManager.getInstanceForLocale(transaction.user.locale);
const tenant = await TenantStorage.getTenant(tenantID);
// Notification Before End Of Charge (Async)
NotificationHandler.sendOptimalChargeReached(
@@ -1452,7 +1452,7 @@ export default class OCPPService {
// Build Inactivity
private transactionInactivityToString(transaction: Transaction, user: User, i18nHourShort = 'h') {
- const i18nManager = new I18nManager(user ? user.locale : Constants.DEFAULT_LANGUAGE);
+ const i18nManager = I18nManager.getInstanceForLocale(user ? user.locale : Constants.DEFAULT_LANGUAGE);
// Get total
const totalInactivitySecs = transaction.stop.totalInactivitySecs;
// None?
@@ -1692,7 +1692,7 @@ export default class OCPPService {
// User provided?
if (user) {
// Get the i18n lib
- const i18nManager = new I18nManager(user.locale);
+ const i18nManager = I18nManager.getInstanceForLocale(user.locale);
const tenant = await TenantStorage.getTenant(tenantID);
// Send Notification (Async)
NotificationHandler.sendEndOfSession(

MODIFY
src/server/rest/v1/service/AuthService.ts
src/server/rest/v1/service/AuthService.ts
@@ -249,7 +249,7 @@ export default class AuthService {
// Save User Status
await UserStorage.saveUserStatus(tenantID, newUser.id, UserStatus.PENDING);
// Get the i18n translation class
- const i18nManager = new I18nManager(newUser.locale);
+ const i18nManager = I18nManager.getInstanceForLocale(newUser.locale);
const tag: Tag = {
id: newUser.name[0] + newUser.firstName[0] + Utils.getRandomIntSafe().toString(),
active: true,

MODIFY
src/server/rest/v1/service/ChargingStationService.ts
src/server/rest/v1/service/ChargingStationService.ts
@@ -1311,7 +1311,7 @@ export default class ChargingStationService {
private static convertOCPPParamsToCSV(ocppParams: OCPPParams, userLocale: string, writeHeader = true): string {
let csv = '';
- const i18nManager = new I18nManager(userLocale);
+ const i18nManager = I18nManager.getInstanceForLocale(userLocale);
// Header
if (writeHeader) {
csv = i18nManager.translate('chargers.chargingStation') + Constants.CSV_SEPARATOR;
@@ -1333,7 +1333,8 @@ export default class ChargingStationService {
private static convertToCSV(req: Request, chargingStations: ChargingStation[], writeHeader = true): string {
let csv = '';
- const i18nManager = new I18nManager(req.user.locale);
+
+ const i18nManager = I18nManager.getInstanceForLocale(req.user.locale);
// Header
if (writeHeader) {
csv = i18nManager.translate('general.name') + Constants.CSV_SEPARATOR;
@@ -1392,7 +1393,7 @@ export default class ChargingStationService {
}
private static async convertQrCodeToPDF(req: Request, pdfDocument: PDFKit.PDFDocument, chargingStations: ChargingStation[]): Promise<void> {
- const i18nManager = new I18nManager(req.user.locale);
+ const i18nManager = I18nManager.getInstanceForLocale(req.user.locale);
// Check for Connector ID
let connectorID = null;
if (req.query.ConnectorID) {

MODIFY
src/server/rest/v1/service/LoggingService.ts
src/server/rest/v1/service/LoggingService.ts
@@ -57,7 +57,7 @@ export default class LoggingService {
private static convertToCSV(req: Request, loggings: Log[], writeHeader = true): string {
let csv = '';
- const i18nManager = new I18nManager(req.user.locale);
+ const i18nManager = I18nManager.getInstanceForLocale(req.user.locale);
// Header
if (writeHeader) {
csv = i18nManager.translate('general.date') + Constants.CSV_SEPARATOR;

MODIFY
src/server/rest/v1/service/StatisticService.ts
src/server/rest/v1/service/StatisticService.ts
@@ -474,7 +474,7 @@ export default class StatisticService {
static convertToCSV(loggedUser: UserToken, transactionStatsMDB: any[], dataCategory: string, dataType: string, year: number | string, dataScope?: string): string {
let user: User;
let unknownUser = Utils.buildUserFullName(user, false, false);
- const i18nManager = new I18nManager(loggedUser.locale);
+ const i18nManager = I18nManager.getInstanceForLocale(loggedUser.locale);
if (!unknownUser) {
unknownUser = 'Unknown';
}

MODIFY
src/server/rest/v1/service/TransactionService.ts
src/server/rest/v1/service/TransactionService.ts
@@ -847,7 +847,7 @@ export default class TransactionService {
public static convertToCSV(req: Request, transactions: Transaction[], writeHeader = true): string {
let csv = '';
- const i18nManager = new I18nManager(req.user.locale);
+ const i18nManager = I18nManager.getInstanceForLocale(req.user.locale);
// Header
if (writeHeader) {
csv = i18nManager.translate('users.id') + Constants.CSV_SEPARATOR;

MODIFY
src/server/rest/v1/service/UserService.ts
src/server/rest/v1/service/UserService.ts
@@ -1078,7 +1078,7 @@ export default class UserService {
private static convertToCSV(req: Request, users: User[], writeHeader = true): string {
let csv = '';
- const i18nManager = new I18nManager(req.user.locale);
+ const i18nManager = I18nManager.getInstanceForLocale(req.user.locale);
// Header
if (writeHeader) {
csv = i18nManager.translate('users.id') + Constants.CSV_SEPARATOR;

MODIFY
src/utils/I18nManager.ts
src/utils/I18nManager.ts
@@ -14,9 +14,10 @@ import i18n from 'i18n-js';
import moment from 'moment';
export default class I18nManager {
+ private static instances = new Map<string, I18nManager>(); // Tableau avec la cle en locale
private language: string;
- public constructor(locale: string) {
+ private constructor(locale: string) {
// Get language
this.language = Utils.getLanguageFromLocale(locale);
// Supported languages?
@@ -26,6 +27,16 @@ export default class I18nManager {
}
}
+ // Get the already existing instance of I18nManager depending on the locale if it exists otherwise we create it
+ public static getInstanceForLocale(locale: string): I18nManager {
+ if (!I18nManager.instances.has(locale)) {
+ I18nManager.instances.set(locale, new I18nManager(locale));
+ }
+
+ return I18nManager.instances.get(locale);
+ }
+
+
public static initialize(): void {
// Get translation files
i18n.translations['en'] = JSON.parse(fs.readFileSync(`${global.appRoot}/assets/i18n/en.json`, 'utf8'));

added "getInstanceForLocale(userLocale)" into I18nManager class
modified all the calls to "new I18nManager()"