@ecopex/ecopex-framework 1.0.12 → 1.0.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ecopex/ecopex-framework",
3
- "version": "1.0.12",
3
+ "version": "1.0.13",
4
4
  "description": "Javascript Framework for API and Admin Panel",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -542,7 +542,7 @@ const checkUnique = async (value = null, field_name = null, tableName = null) =>
542
542
  const sqlErrorHandler = (error, request, reply) => {
543
543
  return reply.status(500).send({
544
544
  status: false,
545
- message: i18n.t('sql.' + error.code.toLowerCase(), request.headers.locale || 'en', {...request.body, ...request.query, ...request.params})
545
+ message: i18n.t('sql.' + error.code.toLowerCase(), {...request.body, ...request.query, ...request.params})
546
546
  });
547
547
  }
548
548
 
package/utils/i18n.js CHANGED
@@ -1,5 +1,6 @@
1
1
  const fs = require('fs');
2
2
  const path = require('path');
3
+ const { config } = require('../stores/config');
3
4
 
4
5
  /**
5
6
  * Internationalization utility for multi-language support
@@ -7,8 +8,10 @@ const path = require('path');
7
8
  class I18n {
8
9
  constructor() {
9
10
  this.locales = {};
10
- this.defaultLocale = 'en';
11
- this.supportedLocales = ['en', 'tr', 'es'];
11
+ this.defaultLocale = config.default_language || 'en';
12
+ this.supportedLocales = config.supported_languages || ['en'];
13
+ this.localesPath = path.join(__dirname, '../locales');
14
+ this.localesBackend = path.join('./locales');
12
15
  this.loadLocales();
13
16
  }
14
17
 
@@ -16,10 +19,8 @@ class I18n {
16
19
  * Load all locale files
17
20
  */
18
21
  loadLocales() {
19
- const localesPath = path.join(__dirname, '../locales');
20
-
21
22
  for (const locale of this.supportedLocales) {
22
- const localePath = path.join(localesPath, locale);
23
+ const localePath = path.join(this.localesPath, locale);
23
24
  if (fs.existsSync(localePath)) {
24
25
  this.locales[locale] = {};
25
26
 
@@ -34,7 +35,24 @@ class I18n {
34
35
  }
35
36
  }
36
37
  }
38
+
39
+ const localesBackend = path.join(this.localesBackend, locale);
40
+ if (fs.existsSync(localesBackend)) {
41
+ const files = fs.readdirSync(localesBackend);
42
+ for (const file of files) {
43
+ if (file.endsWith('.json')) {
44
+ const filePath = path.join(localesBackend, file);
45
+ const content = JSON.parse(fs.readFileSync(filePath, 'utf8'));
46
+ const key = file.replace('.json', '');
47
+ if(!this.locales[locale][key]) {
48
+ this.locales[locale][key] = {};
49
+ }
50
+ this.locales[locale][key] = { ...this.locales[locale][key], ...content };
51
+ }
52
+ }
53
+ }
37
54
  }
55
+
38
56
  }
39
57
 
40
58
  /**
@@ -47,25 +65,40 @@ class I18n {
47
65
  t(key, locale = this.defaultLocale, params = {}) {
48
66
  const keys = key.split('.');
49
67
  let translation = this.locales[locale] || this.locales[this.defaultLocale];
50
-
51
- // Navigate through nested keys
52
- for (const k of keys) {
53
- if (translation && translation[k]) {
54
- translation = translation[k];
55
- } else {
56
- // Fallback to default locale
57
- translation = this.locales[this.defaultLocale];
58
- for (const k of keys) {
59
- if (translation && translation[k]) {
60
- translation = translation[k];
68
+ const fileName = keys.length > 0 ? keys[0] : 'index';
69
+
70
+ if(!translation[fileName]) {
71
+ translation[fileName] = {};
72
+ }
73
+
74
+ if(keys.length > 1) {
75
+ for(const k of keys.slice(1)) {
76
+ if(translation[fileName] && translation[fileName][k] !== undefined) {
77
+ translation = translation[fileName][k];
78
+ } else {
79
+ translation = this.locales[this.defaultLocale];
80
+ if(translation[fileName] && translation[fileName][k] !== undefined) {
81
+ translation = translation[fileName][k];
61
82
  } else {
62
- return key; // Return key if translation not found
83
+ this.writeFile(key, locale, params);
84
+ return key;
63
85
  }
64
86
  }
65
- break;
87
+ }
88
+ } else {
89
+ if(translation[fileName] && translation[fileName][keys[0]] !== undefined) {
90
+ translation = translation[fileName][keys[0]];
91
+ } else {
92
+ translation = this.locales[this.defaultLocale];
93
+ if(translation[fileName] && translation[fileName][keys[0]] !== undefined) {
94
+ translation = translation[fileName][keys[0]];
95
+ } else {
96
+ this.writeFile(key, locale, params);
97
+ return key;
98
+ }
66
99
  }
67
100
  }
68
-
101
+
69
102
  // Replace parameters in the translation
70
103
  if (typeof translation === 'string') {
71
104
  return this.replaceParams(translation, params);
@@ -74,6 +107,27 @@ class I18n {
74
107
  return key;
75
108
  }
76
109
 
110
+ writeFile(key, locale, params) {
111
+ const keys = key.split('.');
112
+ const fileName = keys.length > 1 ? keys[0] : 'index'
113
+
114
+ if(!this.locales[locale]) {
115
+ this.locales[locale] = {};
116
+ }
117
+
118
+ let translations = this.locales[locale][fileName] || {};
119
+
120
+ const paramsString = Object.entries(params).map(([key, value]) => `{ ${key} }`).join(', ');
121
+
122
+ if(keys.slice(1).length > 0) {
123
+ translations[keys.slice(1).join('.')] = (paramsString ? paramsString : '');
124
+ } else {
125
+ translations[keys[0]] = (paramsString ? paramsString : '');
126
+ }
127
+
128
+ fs.writeFileSync(path.join(this.localesBackend, locale, `${fileName}.json`), JSON.stringify(translations, null, 4));
129
+ }
130
+
77
131
  /**
78
132
  * Replace parameters in translation string
79
133
  * @param {string} str - String with parameters
@@ -160,7 +214,7 @@ class I18n {
160
214
  enum: params?.allowedValues ? params.allowedValues.join(', ') : ''
161
215
  };
162
216
 
163
- return this.t(errorKey, locale, errorParams);
217
+ return this.t(errorKey, errorParams);
164
218
  }
165
219
 
166
220
  /**
@@ -15,7 +15,7 @@ class Middleware {
15
15
 
16
16
  // Add locale to request object
17
17
  request.locale = locale;
18
- request.t = (key, params = {}) => i18n.t(key, locale, params);
18
+ request.t = (key, params = {}) => i18n.t(key, params, locale);
19
19
 
20
20
  // Add locale to reply headers
21
21
  reply.header('Content-Language', locale);
@@ -30,8 +30,6 @@ class Middleware {
30
30
  if(config.development) {
31
31
  console.log(error);
32
32
  }
33
-
34
- const locale = request.locale || i18n.detectLanguage(request);
35
33
 
36
34
  if(error.data?.sqlMessage) {
37
35
  return sqlErrorHandler(error, request, reply);
@@ -43,13 +41,13 @@ class Middleware {
43
41
  const field_name = err.instancePath?.replace('/', '') || err.dataPath?.replace('/', '') || err.params?.missingProperty || 'field'
44
42
  return {
45
43
  field: field_name,
46
- message: i18n.t('validation.' + err.keyword, locale, { field: i18n.t('validation.fields.' + field_name, locale) })
44
+ message: i18n.t('validation.' + err.keyword, { field: i18n.t('validation.fields.' + field_name) })
47
45
  }
48
46
  });
49
47
 
50
48
  return reply.status(400).send({
51
49
  status: false,
52
- message: i18n.t('validation.errors.validation', locale),
50
+ message: i18n.t('validation.errors.validation'),
53
51
  details: validationErrors,
54
52
  code: 400
55
53
  });
@@ -145,7 +143,7 @@ class Middleware {
145
143
  const sqlErrorHandler = (error, request, reply) => {
146
144
  return reply.status(500).send({
147
145
  status: false,
148
- message: i18n.t('sql.' + error.data.code.toLowerCase(), request.headers.locale || 'en', {...request.body, ...request.query, ...request.params})
146
+ message: i18n.t('sql.' + error.data.code.toLowerCase(), {...request.body, ...request.query, ...request.params})
149
147
  });
150
148
  }
151
149