@globalart/ownlate-nestjs-translator 1.0.1 → 1.0.3

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/dist/index.cjs CHANGED
@@ -32,39 +32,58 @@ function __decorate(decorators, target, key, desc) {
32
32
  var _ref, _TranslatorService;
33
33
  const TRANSLATIONS_API_URL = "https://api.ownlate.com/public/v1/segments/translations-map";
34
34
  const POLL_INTERVAL_MS = 300 * 1e3;
35
+ const RETRY_INTERVAL_MS = 5 * 1e3;
35
36
  let TranslatorService = _TranslatorService = class TranslatorService {
36
37
  options;
37
38
  httpService;
38
39
  translations = {};
39
40
  pollTimer;
41
+ retryTimer;
40
42
  isLoading = false;
41
43
  logger = new _nestjs_common.Logger(_TranslatorService.name);
42
44
  constructor(options, httpService) {
43
45
  this.options = options;
44
46
  this.httpService = httpService;
45
47
  }
46
- async onModuleInit() {
47
- await this.loadTranslations();
48
+ onModuleInit() {
49
+ this.loadTranslationsSafely();
48
50
  this.pollTimer = setInterval(() => {
49
- this.refreshTranslations();
51
+ this.loadTranslationsSafely();
50
52
  }, POLL_INTERVAL_MS);
51
53
  }
52
54
  onModuleDestroy() {
53
55
  if (this.pollTimer) clearInterval(this.pollTimer);
56
+ this.clearRetryTimer();
54
57
  }
55
- async translate(namespace, key, placeholders) {
56
- const text = this.translations[namespace]?.[key] ?? key;
58
+ translate(namespace, key, placeholders, locale) {
59
+ const resolvedLocale = locale ?? this.options.locale;
60
+ const namespaceTranslations = this.translations[namespace];
61
+ const text = (namespaceTranslations ? this.resolveLocaleTranslations(namespaceTranslations, resolvedLocale) : void 0)?.[key] ?? key;
57
62
  if (!placeholders) return text;
58
63
  return Object.entries(placeholders).reduce((result, [placeholderKey, value]) => result.replace(new RegExp(`\\{\\{${placeholderKey}\\}\\}`, "g"), String(value)), text);
59
64
  }
60
- async refreshTranslations() {
65
+ async loadTranslationsSafely() {
61
66
  if (this.isLoading) return;
62
67
  try {
63
68
  await this.loadTranslations();
69
+ this.clearRetryTimer();
64
70
  } catch (error) {
65
- this.logger.error(`Failed to refresh translations: ${error instanceof Error ? error.message : String(error)}`);
71
+ this.logger.error(`Failed to load translations: ${error instanceof Error ? error.message : String(error)}`);
72
+ this.scheduleRetry();
66
73
  }
67
74
  }
75
+ scheduleRetry() {
76
+ if (this.retryTimer) return;
77
+ this.retryTimer = setTimeout(() => {
78
+ this.retryTimer = void 0;
79
+ this.loadTranslationsSafely();
80
+ }, RETRY_INTERVAL_MS);
81
+ }
82
+ clearRetryTimer() {
83
+ if (!this.retryTimer) return;
84
+ clearTimeout(this.retryTimer);
85
+ this.retryTimer = void 0;
86
+ }
68
87
  async loadTranslations() {
69
88
  this.isLoading = true;
70
89
  try {
@@ -88,15 +107,23 @@ let TranslatorService = _TranslatorService = class TranslatorService {
88
107
  return typeof data === "object" && data !== null;
89
108
  }
90
109
  buildTranslations(data) {
91
- const locale = this.options.locale ?? "en";
92
110
  const filesMap = this.options.filesMap ?? {};
93
111
  const result = {};
94
112
  for (const [fileName, languages] of Object.entries(data)) {
95
113
  const namespace = filesMap[fileName] ?? fileName.replace(/\.json$/, "");
96
- result[namespace] = languages[locale] ?? {};
114
+ result[namespace] = languages;
97
115
  }
98
116
  return result;
99
117
  }
118
+ resolveLocaleTranslations(languages, locale) {
119
+ if (locale) {
120
+ const localeTranslations = languages[locale];
121
+ if (localeTranslations) return localeTranslations;
122
+ }
123
+ const [firstLocale] = Object.keys(languages);
124
+ if (!firstLocale) return {};
125
+ return languages[firstLocale];
126
+ }
100
127
  };
101
128
  TranslatorService = _TranslatorService = __decorate([
102
129
  (0, _nestjs_common.Injectable)(),
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":["ConfigurableModuleBuilder","Logger","HttpModule"],"sources":["../src/translator.module-definition.ts","../src/translator.service.ts","../src/translator.module.ts"],"sourcesContent":["import { ConfigurableModuleBuilder } from \"@nestjs/common\";\nimport type { TranslatorModuleOptions } from \"./translator-module.options\";\n\nexport const {\n ConfigurableModuleClass,\n MODULE_OPTIONS_TOKEN,\n OPTIONS_TYPE,\n} = new ConfigurableModuleBuilder<TranslatorModuleOptions>()\n .setClassMethodName(\"forRoot\")\n .setExtras({ isGlobal: true }, (definition, extras) => ({\n ...definition,\n global: extras.isGlobal,\n }))\n .build();\n","import { HttpService } from \"@nestjs/axios\";\nimport {\n Inject,\n Injectable,\n Logger,\n OnModuleDestroy,\n OnModuleInit,\n} from \"@nestjs/common\";\nimport { firstValueFrom } from \"rxjs\";\nimport type { TranslatorModuleOptions } from \"./translator-module.options\";\nimport { MODULE_OPTIONS_TOKEN } from \"./translator.module-definition\";\nimport type {\n OwnlateTranslationsResponse,\n TranslationPlaceholders,\n} from \"./translator.types\";\n\nconst TRANSLATIONS_API_URL =\n \"https://api.ownlate.com/public/v1/segments/translations-map\";\nconst POLL_INTERVAL_MS = 5 * 60 * 1000;\n\n@Injectable()\nexport class TranslatorService implements OnModuleInit, OnModuleDestroy {\n private translations: Record<string, Record<string, string>> = {};\n private pollTimer?: NodeJS.Timeout;\n private isLoading = false;\n private readonly logger = new Logger(TranslatorService.name);\n\n constructor(\n @Inject(MODULE_OPTIONS_TOKEN)\n private readonly options: TranslatorModuleOptions,\n private readonly httpService: HttpService,\n ) {}\n\n async onModuleInit(): Promise<void> {\n await this.loadTranslations();\n this.pollTimer = setInterval(() => {\n void this.refreshTranslations();\n }, POLL_INTERVAL_MS);\n }\n\n onModuleDestroy(): void {\n if (this.pollTimer) {\n clearInterval(this.pollTimer);\n }\n }\n\n async translate(\n namespace: string,\n key: string,\n placeholders?: TranslationPlaceholders,\n ): Promise<string> {\n const namespaceTranslations = this.translations[namespace];\n const text = namespaceTranslations?.[key] ?? key;\n\n if (!placeholders) {\n return text;\n }\n\n return Object.entries(placeholders).reduce(\n (result, [placeholderKey, value]) =>\n result.replace(\n new RegExp(`\\\\{\\\\{${placeholderKey}\\\\}\\\\}`, \"g\"),\n String(value),\n ),\n text,\n );\n }\n\n private async refreshTranslations(): Promise<void> {\n if (this.isLoading) {\n return;\n }\n\n try {\n await this.loadTranslations();\n } catch (error) {\n this.logger.error(\n `Failed to refresh translations: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n\n private async loadTranslations(): Promise<void> {\n this.isLoading = true;\n\n try {\n const headers: Record<string, string> = {\n Accept: \"application/json\",\n };\n\n if (this.options.apiKey) {\n headers.Authorization = `Bearer ${this.options.apiKey}`;\n }\n\n const { data } = await firstValueFrom(\n this.httpService.get<unknown>(TRANSLATIONS_API_URL, {\n headers,\n params: {\n projectId: this.options.projectId,\n },\n }),\n );\n\n if (this.isErrorResponse(data)) {\n throw new Error(`Failed to load translations: ${data.message}`);\n }\n\n if (!this.isTranslationsResponse(data)) {\n throw new Error(\"Failed to load translations: invalid response format\");\n }\n\n this.translations = this.buildTranslations(data);\n } finally {\n this.isLoading = false;\n }\n }\n\n private isErrorResponse(\n data: unknown,\n ): data is { statusCode: number; message: string } {\n return (\n typeof data === \"object\" &&\n data !== null &&\n \"statusCode\" in data &&\n \"message\" in data\n );\n }\n\n private isTranslationsResponse(\n data: unknown,\n ): data is OwnlateTranslationsResponse {\n return typeof data === \"object\" && data !== null;\n }\n\n private buildTranslations(\n data: OwnlateTranslationsResponse,\n ): Record<string, Record<string, string>> {\n const locale = this.options.locale ?? \"en\";\n const filesMap = this.options.filesMap ?? {};\n const result: Record<string, Record<string, string>> = {};\n\n for (const [fileName, languages] of Object.entries(data)) {\n const namespace =\n filesMap[fileName] ?? fileName.replace(/\\.json$/, \"\");\n result[namespace] = languages[locale] ?? {};\n }\n\n return result;\n }\n}\n","import { HttpModule } from \"@nestjs/axios\";\nimport { Module } from \"@nestjs/common\";\nimport { ConfigurableModuleClass } from \"./translator.module-definition\";\nimport { TranslatorService } from \"./translator.service\";\n\n@Module({\n imports: [HttpModule],\n providers: [TranslatorService],\n exports: [TranslatorService],\n})\nexport class TranslatorModule extends ConfigurableModuleClass {}\n"],"mappings":";;;;;AAGA,MAAa,EACX,yBACA,sBACA,iBACE,IAAIA,eAAAA,0BAAmD,EACxD,mBAAmB,SAAS,EAC5B,UAAU,EAAE,UAAU,KAAK,IAAI,YAAY,YAAY;CACtD,GAAG;CACH,QAAQ,OAAO;AACjB,EAAE,EACD,MAAM;;;;;;;;;;;;;;;;;;;;;;;;ACGT,MAAM,uBACJ;AACF,MAAM,mBAAmB,MAAS;AAG3B,IAAA,oBAAA,qBAAA,MAAM,kBAA2D;CAQnD;CACA;CARnB,eAA+D,CAAC;CAChE;CACA,YAAoB;CACpB,SAA0B,IAAIC,eAAAA,OAAAA,mBAAyB,IAAI;CAE3D,YACE,SAEA,aACA;EAFiB,KAAA,UAAA;EACA,KAAA,cAAA;CAChB;CAEH,MAAM,eAA8B;EAClC,MAAM,KAAK,iBAAiB;EAC5B,KAAK,YAAY,kBAAkB;GACjC,KAAU,oBAAoB;EAChC,GAAG,gBAAgB;CACrB;CAEA,kBAAwB;EACtB,IAAI,KAAK,WACP,cAAc,KAAK,SAAS;CAEhC;CAEA,MAAM,UACJ,WACA,KACA,cACiB;EAEjB,MAAM,OADwB,KAAK,aAAa,aACX,QAAQ;EAE7C,IAAI,CAAC,cACH,OAAO;EAGT,OAAO,OAAO,QAAQ,YAAY,EAAE,QACjC,QAAQ,CAAC,gBAAgB,WACxB,OAAO,QACL,IAAI,OAAO,SAAS,eAAe,SAAS,GAAG,GAC/C,OAAO,KAAK,CACd,GACF,IACF;CACF;CAEA,MAAc,sBAAqC;EACjD,IAAI,KAAK,WACP;EAGF,IAAI;GACF,MAAM,KAAK,iBAAiB;EAC9B,SAAS,OAAO;GACd,KAAK,OAAO,MACV,mCAAmC,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,GAC1F;EACF;CACF;CAEA,MAAc,mBAAkC;EAC9C,KAAK,YAAY;EAEjB,IAAI;GACF,MAAM,UAAkC,EACtC,QAAQ,mBACV;GAEA,IAAI,KAAK,QAAQ,QACf,QAAQ,gBAAgB,UAAU,KAAK,QAAQ;GAGjD,MAAM,EAAE,SAAS,OAAA,GAAA,KAAA,gBACf,KAAK,YAAY,IAAa,sBAAsB;IAClD;IACA,QAAQ,EACN,WAAW,KAAK,QAAQ,UAC1B;GACF,CAAC,CACH;GAEA,IAAI,KAAK,gBAAgB,IAAI,GAC3B,MAAM,IAAI,MAAM,gCAAgC,KAAK,SAAS;GAGhE,IAAI,CAAC,KAAK,uBAAuB,IAAI,GACnC,MAAM,IAAI,MAAM,sDAAsD;GAGxE,KAAK,eAAe,KAAK,kBAAkB,IAAI;EACjD,UAAU;GACR,KAAK,YAAY;EACnB;CACF;CAEA,gBACE,MACiD;EACjD,OACE,OAAO,SAAS,YAChB,SAAS,QACT,gBAAgB,QAChB,aAAa;CAEjB;CAEA,uBACE,MACqC;EACrC,OAAO,OAAO,SAAS,YAAY,SAAS;CAC9C;CAEA,kBACE,MACwC;EACxC,MAAM,SAAS,KAAK,QAAQ,UAAU;EACtC,MAAM,WAAW,KAAK,QAAQ,YAAY,CAAC;EAC3C,MAAM,SAAiD,CAAC;EAExD,KAAK,MAAM,CAAC,UAAU,cAAc,OAAO,QAAQ,IAAI,GAAG;GACxD,MAAM,YACJ,SAAS,aAAa,SAAS,QAAQ,WAAW,EAAE;GACtD,OAAO,aAAa,UAAU,WAAW,CAAC;EAC5C;EAEA,OAAO;CACT;AACF;;gCAjIY;+CAQA,oBAAoB,CAAA;;;;;AClBzB,IAAA,mBAAA,MAAM,yBAAyB,wBAAwB,CAAC;0DALvD;CACN,SAAS,CAACC,cAAAA,UAAU;CACpB,WAAW,CAAC,iBAAiB;CAC7B,SAAS,CAAC,iBAAiB;AAC7B,CAAC,CAAA,GAAA,gBAAA"}
1
+ {"version":3,"file":"index.cjs","names":["ConfigurableModuleBuilder","Logger","HttpModule"],"sources":["../src/translator.module-definition.ts","../src/translator.service.ts","../src/translator.module.ts"],"sourcesContent":["import { ConfigurableModuleBuilder } from \"@nestjs/common\";\nimport type { TranslatorModuleOptions } from \"./translator-module.options\";\n\nexport const {\n ConfigurableModuleClass,\n MODULE_OPTIONS_TOKEN,\n OPTIONS_TYPE,\n} = new ConfigurableModuleBuilder<TranslatorModuleOptions>()\n .setClassMethodName(\"forRoot\")\n .setExtras({ isGlobal: true }, (definition, extras) => ({\n ...definition,\n global: extras.isGlobal,\n }))\n .build();\n","import { HttpService } from \"@nestjs/axios\";\nimport {\n Inject,\n Injectable,\n Logger,\n OnModuleDestroy,\n OnModuleInit,\n} from \"@nestjs/common\";\nimport { firstValueFrom } from \"rxjs\";\nimport type { TranslatorModuleOptions } from \"./translator-module.options\";\nimport { MODULE_OPTIONS_TOKEN } from \"./translator.module-definition\";\nimport type {\n OwnlateTranslationsResponse,\n TranslationPlaceholders,\n} from \"./translator.types\";\n\nconst TRANSLATIONS_API_URL =\n \"https://api.ownlate.com/public/v1/segments/translations-map\";\nconst POLL_INTERVAL_MS = 5 * 60 * 1000;\nconst RETRY_INTERVAL_MS = 5 * 1000;\n\n@Injectable()\nexport class TranslatorService implements OnModuleInit, OnModuleDestroy {\n private translations: Record<string, Record<string, Record<string, string>>> =\n {};\n private pollTimer?: NodeJS.Timeout;\n private retryTimer?: NodeJS.Timeout;\n private isLoading = false;\n private readonly logger = new Logger(TranslatorService.name);\n\n constructor(\n @Inject(MODULE_OPTIONS_TOKEN)\n private readonly options: TranslatorModuleOptions,\n private readonly httpService: HttpService,\n ) {}\n\n onModuleInit(): void {\n void this.loadTranslationsSafely();\n this.pollTimer = setInterval(() => {\n void this.loadTranslationsSafely();\n }, POLL_INTERVAL_MS);\n }\n\n onModuleDestroy(): void {\n if (this.pollTimer) {\n clearInterval(this.pollTimer);\n }\n\n this.clearRetryTimer();\n }\n\n translate(\n namespace: string,\n key: string,\n placeholders?: TranslationPlaceholders,\n locale?: string,\n ): string {\n const resolvedLocale = locale ?? this.options.locale;\n const namespaceTranslations = this.translations[namespace];\n const localeTranslations = namespaceTranslations\n ? this.resolveLocaleTranslations(namespaceTranslations, resolvedLocale)\n : undefined;\n const text = localeTranslations?.[key] ?? key;\n\n if (!placeholders) {\n return text;\n }\n\n return Object.entries(placeholders).reduce(\n (result, [placeholderKey, value]) =>\n result.replace(\n new RegExp(`\\\\{\\\\{${placeholderKey}\\\\}\\\\}`, \"g\"),\n String(value),\n ),\n text,\n );\n }\n\n private async loadTranslationsSafely(): Promise<void> {\n if (this.isLoading) {\n return;\n }\n\n try {\n await this.loadTranslations();\n this.clearRetryTimer();\n } catch (error) {\n this.logger.error(\n `Failed to load translations: ${error instanceof Error ? error.message : String(error)}`,\n );\n this.scheduleRetry();\n }\n }\n\n private scheduleRetry(): void {\n if (this.retryTimer) {\n return;\n }\n\n this.retryTimer = setTimeout(() => {\n this.retryTimer = undefined;\n void this.loadTranslationsSafely();\n }, RETRY_INTERVAL_MS);\n }\n\n private clearRetryTimer(): void {\n if (!this.retryTimer) {\n return;\n }\n\n clearTimeout(this.retryTimer);\n this.retryTimer = undefined;\n }\n\n private async loadTranslations(): Promise<void> {\n this.isLoading = true;\n\n try {\n const headers: Record<string, string> = {\n Accept: \"application/json\",\n };\n\n if (this.options.apiKey) {\n headers.Authorization = `Bearer ${this.options.apiKey}`;\n }\n\n const { data } = await firstValueFrom(\n this.httpService.get<unknown>(TRANSLATIONS_API_URL, {\n headers,\n params: {\n projectId: this.options.projectId,\n },\n }),\n );\n\n if (this.isErrorResponse(data)) {\n throw new Error(`Failed to load translations: ${data.message}`);\n }\n\n if (!this.isTranslationsResponse(data)) {\n throw new Error(\"Failed to load translations: invalid response format\");\n }\n\n this.translations = this.buildTranslations(data);\n } finally {\n this.isLoading = false;\n }\n }\n\n private isErrorResponse(\n data: unknown,\n ): data is { statusCode: number; message: string } {\n return (\n typeof data === \"object\" &&\n data !== null &&\n \"statusCode\" in data &&\n \"message\" in data\n );\n }\n\n private isTranslationsResponse(\n data: unknown,\n ): data is OwnlateTranslationsResponse {\n return typeof data === \"object\" && data !== null;\n }\n\n private buildTranslations(\n data: OwnlateTranslationsResponse,\n ): Record<string, Record<string, Record<string, string>>> {\n const filesMap = this.options.filesMap ?? {};\n const result: Record<string, Record<string, Record<string, string>>> = {};\n\n for (const [fileName, languages] of Object.entries(data)) {\n const namespace = filesMap[fileName] ?? fileName.replace(/\\.json$/, \"\");\n result[namespace] = languages;\n }\n\n return result;\n }\n\n private resolveLocaleTranslations(\n languages: Record<string, Record<string, string>>,\n locale?: string,\n ): Record<string, string> {\n if (locale) {\n const localeTranslations = languages[locale];\n if (localeTranslations) {\n return localeTranslations;\n }\n }\n\n const [firstLocale] = Object.keys(languages);\n if (!firstLocale) {\n return {};\n }\n\n return languages[firstLocale];\n }\n}\n","import { HttpModule } from \"@nestjs/axios\";\nimport { Module } from \"@nestjs/common\";\nimport { ConfigurableModuleClass } from \"./translator.module-definition\";\nimport { TranslatorService } from \"./translator.service\";\n\n@Module({\n imports: [HttpModule],\n providers: [TranslatorService],\n exports: [TranslatorService],\n})\nexport class TranslatorModule extends ConfigurableModuleClass {}\n"],"mappings":"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"}
package/dist/index.d.cts CHANGED
@@ -3,8 +3,8 @@ import { OnModuleDestroy, OnModuleInit } from "@nestjs/common";
3
3
 
4
4
  //#region src/translator-module.options.d.ts
5
5
  interface TranslatorModuleOptions {
6
- apiKey?: string;
7
6
  projectId: string;
7
+ apiKey?: string;
8
8
  locale?: string;
9
9
  filesMap?: Record<string, string>;
10
10
  }
@@ -29,17 +29,21 @@ declare class TranslatorService implements OnModuleInit, OnModuleDestroy {
29
29
  private readonly httpService;
30
30
  private translations;
31
31
  private pollTimer?;
32
+ private retryTimer?;
32
33
  private isLoading;
33
34
  private readonly logger;
34
35
  constructor(options: TranslatorModuleOptions, httpService: HttpService);
35
- onModuleInit(): Promise<void>;
36
+ onModuleInit(): void;
36
37
  onModuleDestroy(): void;
37
- translate(namespace: string, key: string, placeholders?: TranslationPlaceholders): Promise<string>;
38
- private refreshTranslations;
38
+ translate(namespace: string, key: string, placeholders?: TranslationPlaceholders, locale?: string): string;
39
+ private loadTranslationsSafely;
40
+ private scheduleRetry;
41
+ private clearRetryTimer;
39
42
  private loadTranslations;
40
43
  private isErrorResponse;
41
44
  private isTranslationsResponse;
42
45
  private buildTranslations;
46
+ private resolveLocaleTranslations;
43
47
  }
44
48
  //#endregion
45
49
  export { type OwnlateTranslationsResponse, type TranslationPlaceholders, TranslatorModule, type TranslatorModuleOptions, TranslatorService };
package/dist/index.d.mts CHANGED
@@ -3,8 +3,8 @@ import { OnModuleDestroy, OnModuleInit } from "@nestjs/common";
3
3
 
4
4
  //#region src/translator-module.options.d.ts
5
5
  interface TranslatorModuleOptions {
6
- apiKey?: string;
7
6
  projectId: string;
7
+ apiKey?: string;
8
8
  locale?: string;
9
9
  filesMap?: Record<string, string>;
10
10
  }
@@ -29,17 +29,21 @@ declare class TranslatorService implements OnModuleInit, OnModuleDestroy {
29
29
  private readonly httpService;
30
30
  private translations;
31
31
  private pollTimer?;
32
+ private retryTimer?;
32
33
  private isLoading;
33
34
  private readonly logger;
34
35
  constructor(options: TranslatorModuleOptions, httpService: HttpService);
35
- onModuleInit(): Promise<void>;
36
+ onModuleInit(): void;
36
37
  onModuleDestroy(): void;
37
- translate(namespace: string, key: string, placeholders?: TranslationPlaceholders): Promise<string>;
38
- private refreshTranslations;
38
+ translate(namespace: string, key: string, placeholders?: TranslationPlaceholders, locale?: string): string;
39
+ private loadTranslationsSafely;
40
+ private scheduleRetry;
41
+ private clearRetryTimer;
39
42
  private loadTranslations;
40
43
  private isErrorResponse;
41
44
  private isTranslationsResponse;
42
45
  private buildTranslations;
46
+ private resolveLocaleTranslations;
43
47
  }
44
48
  //#endregion
45
49
  export { type OwnlateTranslationsResponse, type TranslationPlaceholders, TranslatorModule, type TranslatorModuleOptions, TranslatorService };
package/dist/index.mjs CHANGED
@@ -31,39 +31,58 @@ function __decorate(decorators, target, key, desc) {
31
31
  var _ref, _TranslatorService;
32
32
  const TRANSLATIONS_API_URL = "https://api.ownlate.com/public/v1/segments/translations-map";
33
33
  const POLL_INTERVAL_MS = 300 * 1e3;
34
+ const RETRY_INTERVAL_MS = 5 * 1e3;
34
35
  let TranslatorService = _TranslatorService = class TranslatorService {
35
36
  options;
36
37
  httpService;
37
38
  translations = {};
38
39
  pollTimer;
40
+ retryTimer;
39
41
  isLoading = false;
40
42
  logger = new Logger(_TranslatorService.name);
41
43
  constructor(options, httpService) {
42
44
  this.options = options;
43
45
  this.httpService = httpService;
44
46
  }
45
- async onModuleInit() {
46
- await this.loadTranslations();
47
+ onModuleInit() {
48
+ this.loadTranslationsSafely();
47
49
  this.pollTimer = setInterval(() => {
48
- this.refreshTranslations();
50
+ this.loadTranslationsSafely();
49
51
  }, POLL_INTERVAL_MS);
50
52
  }
51
53
  onModuleDestroy() {
52
54
  if (this.pollTimer) clearInterval(this.pollTimer);
55
+ this.clearRetryTimer();
53
56
  }
54
- async translate(namespace, key, placeholders) {
55
- const text = this.translations[namespace]?.[key] ?? key;
57
+ translate(namespace, key, placeholders, locale) {
58
+ const resolvedLocale = locale ?? this.options.locale;
59
+ const namespaceTranslations = this.translations[namespace];
60
+ const text = (namespaceTranslations ? this.resolveLocaleTranslations(namespaceTranslations, resolvedLocale) : void 0)?.[key] ?? key;
56
61
  if (!placeholders) return text;
57
62
  return Object.entries(placeholders).reduce((result, [placeholderKey, value]) => result.replace(new RegExp(`\\{\\{${placeholderKey}\\}\\}`, "g"), String(value)), text);
58
63
  }
59
- async refreshTranslations() {
64
+ async loadTranslationsSafely() {
60
65
  if (this.isLoading) return;
61
66
  try {
62
67
  await this.loadTranslations();
68
+ this.clearRetryTimer();
63
69
  } catch (error) {
64
- this.logger.error(`Failed to refresh translations: ${error instanceof Error ? error.message : String(error)}`);
70
+ this.logger.error(`Failed to load translations: ${error instanceof Error ? error.message : String(error)}`);
71
+ this.scheduleRetry();
65
72
  }
66
73
  }
74
+ scheduleRetry() {
75
+ if (this.retryTimer) return;
76
+ this.retryTimer = setTimeout(() => {
77
+ this.retryTimer = void 0;
78
+ this.loadTranslationsSafely();
79
+ }, RETRY_INTERVAL_MS);
80
+ }
81
+ clearRetryTimer() {
82
+ if (!this.retryTimer) return;
83
+ clearTimeout(this.retryTimer);
84
+ this.retryTimer = void 0;
85
+ }
67
86
  async loadTranslations() {
68
87
  this.isLoading = true;
69
88
  try {
@@ -87,15 +106,23 @@ let TranslatorService = _TranslatorService = class TranslatorService {
87
106
  return typeof data === "object" && data !== null;
88
107
  }
89
108
  buildTranslations(data) {
90
- const locale = this.options.locale ?? "en";
91
109
  const filesMap = this.options.filesMap ?? {};
92
110
  const result = {};
93
111
  for (const [fileName, languages] of Object.entries(data)) {
94
112
  const namespace = filesMap[fileName] ?? fileName.replace(/\.json$/, "");
95
- result[namespace] = languages[locale] ?? {};
113
+ result[namespace] = languages;
96
114
  }
97
115
  return result;
98
116
  }
117
+ resolveLocaleTranslations(languages, locale) {
118
+ if (locale) {
119
+ const localeTranslations = languages[locale];
120
+ if (localeTranslations) return localeTranslations;
121
+ }
122
+ const [firstLocale] = Object.keys(languages);
123
+ if (!firstLocale) return {};
124
+ return languages[firstLocale];
125
+ }
99
126
  };
100
127
  TranslatorService = _TranslatorService = __decorate([
101
128
  Injectable(),
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../src/translator.module-definition.ts","../src/translator.service.ts","../src/translator.module.ts"],"sourcesContent":["import { ConfigurableModuleBuilder } from \"@nestjs/common\";\nimport type { TranslatorModuleOptions } from \"./translator-module.options\";\n\nexport const {\n ConfigurableModuleClass,\n MODULE_OPTIONS_TOKEN,\n OPTIONS_TYPE,\n} = new ConfigurableModuleBuilder<TranslatorModuleOptions>()\n .setClassMethodName(\"forRoot\")\n .setExtras({ isGlobal: true }, (definition, extras) => ({\n ...definition,\n global: extras.isGlobal,\n }))\n .build();\n","import { HttpService } from \"@nestjs/axios\";\nimport {\n Inject,\n Injectable,\n Logger,\n OnModuleDestroy,\n OnModuleInit,\n} from \"@nestjs/common\";\nimport { firstValueFrom } from \"rxjs\";\nimport type { TranslatorModuleOptions } from \"./translator-module.options\";\nimport { MODULE_OPTIONS_TOKEN } from \"./translator.module-definition\";\nimport type {\n OwnlateTranslationsResponse,\n TranslationPlaceholders,\n} from \"./translator.types\";\n\nconst TRANSLATIONS_API_URL =\n \"https://api.ownlate.com/public/v1/segments/translations-map\";\nconst POLL_INTERVAL_MS = 5 * 60 * 1000;\n\n@Injectable()\nexport class TranslatorService implements OnModuleInit, OnModuleDestroy {\n private translations: Record<string, Record<string, string>> = {};\n private pollTimer?: NodeJS.Timeout;\n private isLoading = false;\n private readonly logger = new Logger(TranslatorService.name);\n\n constructor(\n @Inject(MODULE_OPTIONS_TOKEN)\n private readonly options: TranslatorModuleOptions,\n private readonly httpService: HttpService,\n ) {}\n\n async onModuleInit(): Promise<void> {\n await this.loadTranslations();\n this.pollTimer = setInterval(() => {\n void this.refreshTranslations();\n }, POLL_INTERVAL_MS);\n }\n\n onModuleDestroy(): void {\n if (this.pollTimer) {\n clearInterval(this.pollTimer);\n }\n }\n\n async translate(\n namespace: string,\n key: string,\n placeholders?: TranslationPlaceholders,\n ): Promise<string> {\n const namespaceTranslations = this.translations[namespace];\n const text = namespaceTranslations?.[key] ?? key;\n\n if (!placeholders) {\n return text;\n }\n\n return Object.entries(placeholders).reduce(\n (result, [placeholderKey, value]) =>\n result.replace(\n new RegExp(`\\\\{\\\\{${placeholderKey}\\\\}\\\\}`, \"g\"),\n String(value),\n ),\n text,\n );\n }\n\n private async refreshTranslations(): Promise<void> {\n if (this.isLoading) {\n return;\n }\n\n try {\n await this.loadTranslations();\n } catch (error) {\n this.logger.error(\n `Failed to refresh translations: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n\n private async loadTranslations(): Promise<void> {\n this.isLoading = true;\n\n try {\n const headers: Record<string, string> = {\n Accept: \"application/json\",\n };\n\n if (this.options.apiKey) {\n headers.Authorization = `Bearer ${this.options.apiKey}`;\n }\n\n const { data } = await firstValueFrom(\n this.httpService.get<unknown>(TRANSLATIONS_API_URL, {\n headers,\n params: {\n projectId: this.options.projectId,\n },\n }),\n );\n\n if (this.isErrorResponse(data)) {\n throw new Error(`Failed to load translations: ${data.message}`);\n }\n\n if (!this.isTranslationsResponse(data)) {\n throw new Error(\"Failed to load translations: invalid response format\");\n }\n\n this.translations = this.buildTranslations(data);\n } finally {\n this.isLoading = false;\n }\n }\n\n private isErrorResponse(\n data: unknown,\n ): data is { statusCode: number; message: string } {\n return (\n typeof data === \"object\" &&\n data !== null &&\n \"statusCode\" in data &&\n \"message\" in data\n );\n }\n\n private isTranslationsResponse(\n data: unknown,\n ): data is OwnlateTranslationsResponse {\n return typeof data === \"object\" && data !== null;\n }\n\n private buildTranslations(\n data: OwnlateTranslationsResponse,\n ): Record<string, Record<string, string>> {\n const locale = this.options.locale ?? \"en\";\n const filesMap = this.options.filesMap ?? {};\n const result: Record<string, Record<string, string>> = {};\n\n for (const [fileName, languages] of Object.entries(data)) {\n const namespace =\n filesMap[fileName] ?? fileName.replace(/\\.json$/, \"\");\n result[namespace] = languages[locale] ?? {};\n }\n\n return result;\n }\n}\n","import { HttpModule } from \"@nestjs/axios\";\nimport { Module } from \"@nestjs/common\";\nimport { ConfigurableModuleClass } from \"./translator.module-definition\";\nimport { TranslatorService } from \"./translator.service\";\n\n@Module({\n imports: [HttpModule],\n providers: [TranslatorService],\n exports: [TranslatorService],\n})\nexport class TranslatorModule extends ConfigurableModuleClass {}\n"],"mappings":";;;;AAGA,MAAa,EACX,yBACA,sBACA,iBACE,IAAI,0BAAmD,EACxD,mBAAmB,SAAS,EAC5B,UAAU,EAAE,UAAU,KAAK,IAAI,YAAY,YAAY;CACtD,GAAG;CACH,QAAQ,OAAO;AACjB,EAAE,EACD,MAAM;;;;;;;;;;;;;;;;;;;;;;;;ACGT,MAAM,uBACJ;AACF,MAAM,mBAAmB,MAAS;AAG3B,IAAA,oBAAA,qBAAA,MAAM,kBAA2D;CAQnD;CACA;CARnB,eAA+D,CAAC;CAChE;CACA,YAAoB;CACpB,SAA0B,IAAI,OAAA,mBAAyB,IAAI;CAE3D,YACE,SAEA,aACA;EAFiB,KAAA,UAAA;EACA,KAAA,cAAA;CAChB;CAEH,MAAM,eAA8B;EAClC,MAAM,KAAK,iBAAiB;EAC5B,KAAK,YAAY,kBAAkB;GACjC,KAAU,oBAAoB;EAChC,GAAG,gBAAgB;CACrB;CAEA,kBAAwB;EACtB,IAAI,KAAK,WACP,cAAc,KAAK,SAAS;CAEhC;CAEA,MAAM,UACJ,WACA,KACA,cACiB;EAEjB,MAAM,OADwB,KAAK,aAAa,aACX,QAAQ;EAE7C,IAAI,CAAC,cACH,OAAO;EAGT,OAAO,OAAO,QAAQ,YAAY,EAAE,QACjC,QAAQ,CAAC,gBAAgB,WACxB,OAAO,QACL,IAAI,OAAO,SAAS,eAAe,SAAS,GAAG,GAC/C,OAAO,KAAK,CACd,GACF,IACF;CACF;CAEA,MAAc,sBAAqC;EACjD,IAAI,KAAK,WACP;EAGF,IAAI;GACF,MAAM,KAAK,iBAAiB;EAC9B,SAAS,OAAO;GACd,KAAK,OAAO,MACV,mCAAmC,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,GAC1F;EACF;CACF;CAEA,MAAc,mBAAkC;EAC9C,KAAK,YAAY;EAEjB,IAAI;GACF,MAAM,UAAkC,EACtC,QAAQ,mBACV;GAEA,IAAI,KAAK,QAAQ,QACf,QAAQ,gBAAgB,UAAU,KAAK,QAAQ;GAGjD,MAAM,EAAE,SAAS,MAAM,eACrB,KAAK,YAAY,IAAa,sBAAsB;IAClD;IACA,QAAQ,EACN,WAAW,KAAK,QAAQ,UAC1B;GACF,CAAC,CACH;GAEA,IAAI,KAAK,gBAAgB,IAAI,GAC3B,MAAM,IAAI,MAAM,gCAAgC,KAAK,SAAS;GAGhE,IAAI,CAAC,KAAK,uBAAuB,IAAI,GACnC,MAAM,IAAI,MAAM,sDAAsD;GAGxE,KAAK,eAAe,KAAK,kBAAkB,IAAI;EACjD,UAAU;GACR,KAAK,YAAY;EACnB;CACF;CAEA,gBACE,MACiD;EACjD,OACE,OAAO,SAAS,YAChB,SAAS,QACT,gBAAgB,QAChB,aAAa;CAEjB;CAEA,uBACE,MACqC;EACrC,OAAO,OAAO,SAAS,YAAY,SAAS;CAC9C;CAEA,kBACE,MACwC;EACxC,MAAM,SAAS,KAAK,QAAQ,UAAU;EACtC,MAAM,WAAW,KAAK,QAAQ,YAAY,CAAC;EAC3C,MAAM,SAAiD,CAAC;EAExD,KAAK,MAAM,CAAC,UAAU,cAAc,OAAO,QAAQ,IAAI,GAAG;GACxD,MAAM,YACJ,SAAS,aAAa,SAAS,QAAQ,WAAW,EAAE;GACtD,OAAO,aAAa,UAAU,WAAW,CAAC;EAC5C;EAEA,OAAO;CACT;AACF;;CAjIC,WAAW;oBAQP,OAAO,oBAAoB,CAAA;;;;;AClBzB,IAAA,mBAAA,MAAM,yBAAyB,wBAAwB,CAAC;+BAL9D,OAAO;CACN,SAAS,CAAC,UAAU;CACpB,WAAW,CAAC,iBAAiB;CAC7B,SAAS,CAAC,iBAAiB;AAC7B,CAAC,CAAA,GAAA,gBAAA"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../src/translator.module-definition.ts","../src/translator.service.ts","../src/translator.module.ts"],"sourcesContent":["import { ConfigurableModuleBuilder } from \"@nestjs/common\";\nimport type { TranslatorModuleOptions } from \"./translator-module.options\";\n\nexport const {\n ConfigurableModuleClass,\n MODULE_OPTIONS_TOKEN,\n OPTIONS_TYPE,\n} = new ConfigurableModuleBuilder<TranslatorModuleOptions>()\n .setClassMethodName(\"forRoot\")\n .setExtras({ isGlobal: true }, (definition, extras) => ({\n ...definition,\n global: extras.isGlobal,\n }))\n .build();\n","import { HttpService } from \"@nestjs/axios\";\nimport {\n Inject,\n Injectable,\n Logger,\n OnModuleDestroy,\n OnModuleInit,\n} from \"@nestjs/common\";\nimport { firstValueFrom } from \"rxjs\";\nimport type { TranslatorModuleOptions } from \"./translator-module.options\";\nimport { MODULE_OPTIONS_TOKEN } from \"./translator.module-definition\";\nimport type {\n OwnlateTranslationsResponse,\n TranslationPlaceholders,\n} from \"./translator.types\";\n\nconst TRANSLATIONS_API_URL =\n \"https://api.ownlate.com/public/v1/segments/translations-map\";\nconst POLL_INTERVAL_MS = 5 * 60 * 1000;\nconst RETRY_INTERVAL_MS = 5 * 1000;\n\n@Injectable()\nexport class TranslatorService implements OnModuleInit, OnModuleDestroy {\n private translations: Record<string, Record<string, Record<string, string>>> =\n {};\n private pollTimer?: NodeJS.Timeout;\n private retryTimer?: NodeJS.Timeout;\n private isLoading = false;\n private readonly logger = new Logger(TranslatorService.name);\n\n constructor(\n @Inject(MODULE_OPTIONS_TOKEN)\n private readonly options: TranslatorModuleOptions,\n private readonly httpService: HttpService,\n ) {}\n\n onModuleInit(): void {\n void this.loadTranslationsSafely();\n this.pollTimer = setInterval(() => {\n void this.loadTranslationsSafely();\n }, POLL_INTERVAL_MS);\n }\n\n onModuleDestroy(): void {\n if (this.pollTimer) {\n clearInterval(this.pollTimer);\n }\n\n this.clearRetryTimer();\n }\n\n translate(\n namespace: string,\n key: string,\n placeholders?: TranslationPlaceholders,\n locale?: string,\n ): string {\n const resolvedLocale = locale ?? this.options.locale;\n const namespaceTranslations = this.translations[namespace];\n const localeTranslations = namespaceTranslations\n ? this.resolveLocaleTranslations(namespaceTranslations, resolvedLocale)\n : undefined;\n const text = localeTranslations?.[key] ?? key;\n\n if (!placeholders) {\n return text;\n }\n\n return Object.entries(placeholders).reduce(\n (result, [placeholderKey, value]) =>\n result.replace(\n new RegExp(`\\\\{\\\\{${placeholderKey}\\\\}\\\\}`, \"g\"),\n String(value),\n ),\n text,\n );\n }\n\n private async loadTranslationsSafely(): Promise<void> {\n if (this.isLoading) {\n return;\n }\n\n try {\n await this.loadTranslations();\n this.clearRetryTimer();\n } catch (error) {\n this.logger.error(\n `Failed to load translations: ${error instanceof Error ? error.message : String(error)}`,\n );\n this.scheduleRetry();\n }\n }\n\n private scheduleRetry(): void {\n if (this.retryTimer) {\n return;\n }\n\n this.retryTimer = setTimeout(() => {\n this.retryTimer = undefined;\n void this.loadTranslationsSafely();\n }, RETRY_INTERVAL_MS);\n }\n\n private clearRetryTimer(): void {\n if (!this.retryTimer) {\n return;\n }\n\n clearTimeout(this.retryTimer);\n this.retryTimer = undefined;\n }\n\n private async loadTranslations(): Promise<void> {\n this.isLoading = true;\n\n try {\n const headers: Record<string, string> = {\n Accept: \"application/json\",\n };\n\n if (this.options.apiKey) {\n headers.Authorization = `Bearer ${this.options.apiKey}`;\n }\n\n const { data } = await firstValueFrom(\n this.httpService.get<unknown>(TRANSLATIONS_API_URL, {\n headers,\n params: {\n projectId: this.options.projectId,\n },\n }),\n );\n\n if (this.isErrorResponse(data)) {\n throw new Error(`Failed to load translations: ${data.message}`);\n }\n\n if (!this.isTranslationsResponse(data)) {\n throw new Error(\"Failed to load translations: invalid response format\");\n }\n\n this.translations = this.buildTranslations(data);\n } finally {\n this.isLoading = false;\n }\n }\n\n private isErrorResponse(\n data: unknown,\n ): data is { statusCode: number; message: string } {\n return (\n typeof data === \"object\" &&\n data !== null &&\n \"statusCode\" in data &&\n \"message\" in data\n );\n }\n\n private isTranslationsResponse(\n data: unknown,\n ): data is OwnlateTranslationsResponse {\n return typeof data === \"object\" && data !== null;\n }\n\n private buildTranslations(\n data: OwnlateTranslationsResponse,\n ): Record<string, Record<string, Record<string, string>>> {\n const filesMap = this.options.filesMap ?? {};\n const result: Record<string, Record<string, Record<string, string>>> = {};\n\n for (const [fileName, languages] of Object.entries(data)) {\n const namespace = filesMap[fileName] ?? fileName.replace(/\\.json$/, \"\");\n result[namespace] = languages;\n }\n\n return result;\n }\n\n private resolveLocaleTranslations(\n languages: Record<string, Record<string, string>>,\n locale?: string,\n ): Record<string, string> {\n if (locale) {\n const localeTranslations = languages[locale];\n if (localeTranslations) {\n return localeTranslations;\n }\n }\n\n const [firstLocale] = Object.keys(languages);\n if (!firstLocale) {\n return {};\n }\n\n return languages[firstLocale];\n }\n}\n","import { HttpModule } from \"@nestjs/axios\";\nimport { Module } from \"@nestjs/common\";\nimport { ConfigurableModuleClass } from \"./translator.module-definition\";\nimport { TranslatorService } from \"./translator.service\";\n\n@Module({\n imports: [HttpModule],\n providers: [TranslatorService],\n exports: [TranslatorService],\n})\nexport class TranslatorModule extends ConfigurableModuleClass {}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@globalart/ownlate-nestjs-translator",
3
- "version": "1.0.1",
3
+ "version": "1.0.3",
4
4
  "description": "",
5
5
  "license": "ISC",
6
6
  "type": "module",