@flusys/nestjs-localization 4.0.0-rc
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/README.md +870 -0
- package/cjs/config/index.js +19 -0
- package/cjs/config/localization.constants.js +20 -0
- package/cjs/config/message-keys.js +77 -0
- package/cjs/controllers/index.js +20 -0
- package/cjs/controllers/language.controller.js +188 -0
- package/cjs/controllers/translation-key.controller.js +174 -0
- package/cjs/controllers/translation.controller.js +254 -0
- package/cjs/dtos/index.js +20 -0
- package/cjs/dtos/language.dto.js +205 -0
- package/cjs/dtos/translation-key.dto.js +233 -0
- package/cjs/dtos/translation.dto.js +298 -0
- package/cjs/entities/index.js +42 -0
- package/cjs/entities/language.entity.js +126 -0
- package/cjs/entities/translation-key.entity.js +125 -0
- package/cjs/entities/translation.entity.js +120 -0
- package/cjs/index.js +24 -0
- package/cjs/interfaces/index.js +21 -0
- package/cjs/interfaces/language.interface.js +4 -0
- package/cjs/interfaces/localization-module-options.interface.js +4 -0
- package/cjs/interfaces/translation-key.interface.js +4 -0
- package/cjs/interfaces/translation.interface.js +4 -0
- package/cjs/modules/index.js +18 -0
- package/cjs/modules/localization.module.js +115 -0
- package/cjs/services/index.js +22 -0
- package/cjs/services/language.service.js +108 -0
- package/cjs/services/localization-config.service.js +66 -0
- package/cjs/services/localization-datasource.provider.js +122 -0
- package/cjs/services/translation-key.service.js +184 -0
- package/cjs/services/translation.service.js +222 -0
- package/config/index.d.ts +2 -0
- package/config/localization.constants.d.ts +2 -0
- package/config/message-keys.d.ts +96 -0
- package/controllers/index.d.ts +3 -0
- package/controllers/language.controller.d.ts +25 -0
- package/controllers/translation-key.controller.d.ts +22 -0
- package/controllers/translation.controller.d.ts +25 -0
- package/dtos/index.d.ts +3 -0
- package/dtos/language.dto.d.ts +24 -0
- package/dtos/translation-key.dto.d.ts +29 -0
- package/dtos/translation.dto.d.ts +42 -0
- package/entities/index.d.ts +8 -0
- package/entities/language.entity.d.ts +13 -0
- package/entities/translation-key.entity.d.ts +13 -0
- package/entities/translation.entity.d.ts +12 -0
- package/fesm/config/index.js +2 -0
- package/fesm/config/localization.constants.js +2 -0
- package/fesm/config/message-keys.js +54 -0
- package/fesm/controllers/index.js +3 -0
- package/fesm/controllers/language.controller.js +178 -0
- package/fesm/controllers/translation-key.controller.js +164 -0
- package/fesm/controllers/translation.controller.js +244 -0
- package/fesm/dtos/index.js +3 -0
- package/fesm/dtos/language.dto.js +184 -0
- package/fesm/dtos/translation-key.dto.js +209 -0
- package/fesm/dtos/translation.dto.js +265 -0
- package/fesm/entities/index.js +14 -0
- package/fesm/entities/language.entity.js +116 -0
- package/fesm/entities/translation-key.entity.js +115 -0
- package/fesm/entities/translation.entity.js +110 -0
- package/fesm/index.js +7 -0
- package/fesm/interfaces/index.js +4 -0
- package/fesm/interfaces/language.interface.js +1 -0
- package/fesm/interfaces/localization-module-options.interface.js +1 -0
- package/fesm/interfaces/translation-key.interface.js +1 -0
- package/fesm/interfaces/translation.interface.js +1 -0
- package/fesm/modules/index.js +1 -0
- package/fesm/modules/localization.module.js +105 -0
- package/fesm/services/index.js +5 -0
- package/fesm/services/language.service.js +98 -0
- package/fesm/services/localization-config.service.js +56 -0
- package/fesm/services/localization-datasource.provider.js +112 -0
- package/fesm/services/translation-key.service.js +174 -0
- package/fesm/services/translation.service.js +212 -0
- package/index.d.ts +7 -0
- package/interfaces/index.d.ts +4 -0
- package/interfaces/language.interface.d.ts +10 -0
- package/interfaces/localization-module-options.interface.d.ts +21 -0
- package/interfaces/translation-key.interface.d.ts +11 -0
- package/interfaces/translation.interface.d.ts +13 -0
- package/modules/index.d.ts +1 -0
- package/modules/localization.module.d.ts +8 -0
- package/package.json +80 -0
- package/services/index.d.ts +5 -0
- package/services/language.service.d.ts +18 -0
- package/services/localization-config.service.d.ts +11 -0
- package/services/localization-datasource.provider.d.ts +16 -0
- package/services/translation-key.service.d.ts +23 -0
- package/services/translation.service.d.ts +30 -0
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
function _define_property(obj, key, value) {
|
|
2
|
+
if (key in obj) {
|
|
3
|
+
Object.defineProperty(obj, key, {
|
|
4
|
+
value: value,
|
|
5
|
+
enumerable: true,
|
|
6
|
+
configurable: true,
|
|
7
|
+
writable: true
|
|
8
|
+
});
|
|
9
|
+
} else {
|
|
10
|
+
obj[key] = value;
|
|
11
|
+
}
|
|
12
|
+
return obj;
|
|
13
|
+
}
|
|
14
|
+
function _ts_decorate(decorators, target, key, desc) {
|
|
15
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
16
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
17
|
+
else for(var i = decorators.length - 1; i >= 0; i--)if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
18
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
19
|
+
}
|
|
20
|
+
function _ts_metadata(k, v) {
|
|
21
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
22
|
+
}
|
|
23
|
+
function _ts_param(paramIndex, decorator) {
|
|
24
|
+
return function(target, key) {
|
|
25
|
+
decorator(target, key, paramIndex);
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
import { HybridCache, RequestScopedApiService } from '@flusys/nestjs-shared/classes';
|
|
29
|
+
import { UtilsService } from '@flusys/nestjs-shared/modules';
|
|
30
|
+
import { Inject, Injectable, Scope } from '@nestjs/common';
|
|
31
|
+
import { In, IsNull } from 'typeorm';
|
|
32
|
+
import { Translation, Language, TranslationKey } from '../entities';
|
|
33
|
+
import { LocalizationDataSourceProvider } from './localization-datasource.provider';
|
|
34
|
+
export class TranslationService extends RequestScopedApiService {
|
|
35
|
+
resolveEntity() {
|
|
36
|
+
return Translation;
|
|
37
|
+
}
|
|
38
|
+
getDataSourceProvider() {
|
|
39
|
+
return this.dataSourceProvider;
|
|
40
|
+
}
|
|
41
|
+
async getFilterQuery(query, filter, _user) {
|
|
42
|
+
// Handle module filter by joining to translation_key table
|
|
43
|
+
if (filter.module) {
|
|
44
|
+
query.innerJoin('translation.translationKey', 'tk');
|
|
45
|
+
query.andWhere('tk.module = :module', {
|
|
46
|
+
module: filter.module
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
// Handle standard filters on translation table
|
|
50
|
+
if (filter.languageId) {
|
|
51
|
+
query.andWhere('translation.languageId = :languageId', {
|
|
52
|
+
languageId: filter.languageId
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
if (filter.translationKeyId) {
|
|
56
|
+
query.andWhere('translation.translationKeyId = :translationKeyId', {
|
|
57
|
+
translationKeyId: filter.translationKeyId
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
return {
|
|
61
|
+
query,
|
|
62
|
+
isRaw: false
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
async ensureAllReposInitialized() {
|
|
66
|
+
await this.ensureRepositoryInitialized();
|
|
67
|
+
if (!this.languageRepo) {
|
|
68
|
+
const ds = await this.dataSourceProvider.getDataSource();
|
|
69
|
+
this.languageRepo = ds.getRepository(Language);
|
|
70
|
+
this.translationKeyRepo = ds.getRepository(TranslationKey);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
async getByLanguageCode(languageCode, modules) {
|
|
74
|
+
await this.ensureAllReposInitialized();
|
|
75
|
+
const language = await this.findActiveLanguageByCode(languageCode);
|
|
76
|
+
if (!language) return {};
|
|
77
|
+
const qb = this.repository.createQueryBuilder('t').innerJoinAndSelect('t.translationKey', 'tk').where('t.language_id = :languageId', {
|
|
78
|
+
languageId: language.id
|
|
79
|
+
}).andWhere('t.is_active = true').andWhere('t.deleted_at IS NULL').andWhere('tk.is_active = true').andWhere('tk.deleted_at IS NULL');
|
|
80
|
+
if (modules && modules.length > 0) {
|
|
81
|
+
qb.andWhere('tk.module IN (:...modules)', {
|
|
82
|
+
modules
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
return this.toTranslationsMap(await qb.getMany());
|
|
86
|
+
}
|
|
87
|
+
async getByModuleAndLanguage(module, languageCode) {
|
|
88
|
+
await this.ensureAllReposInitialized();
|
|
89
|
+
const language = await this.findActiveLanguageByCode(languageCode);
|
|
90
|
+
if (!language) return {};
|
|
91
|
+
const translations = await this.repository.createQueryBuilder('t').innerJoinAndSelect('t.translationKey', 'tk').where('t.language_id = :languageId', {
|
|
92
|
+
languageId: language.id
|
|
93
|
+
}).andWhere('tk.module = :module', {
|
|
94
|
+
module
|
|
95
|
+
}).andWhere('t.is_active = true').andWhere('t.deleted_at IS NULL').andWhere('tk.is_active = true').andWhere('tk.deleted_at IS NULL').getMany();
|
|
96
|
+
return this.toTranslationsMap(translations);
|
|
97
|
+
}
|
|
98
|
+
async bulkUpdate(updates) {
|
|
99
|
+
await this.ensureRepositoryInitialized();
|
|
100
|
+
if (updates.length === 0) return [];
|
|
101
|
+
const ds = await this.dataSourceProvider.getDataSource();
|
|
102
|
+
const queryRunner = ds.createQueryRunner();
|
|
103
|
+
await queryRunner.connect();
|
|
104
|
+
await queryRunner.startTransaction();
|
|
105
|
+
try {
|
|
106
|
+
const resultIds = [];
|
|
107
|
+
for (const update of updates){
|
|
108
|
+
if (update.id) {
|
|
109
|
+
// Update existing translation
|
|
110
|
+
await queryRunner.manager.update(Translation, {
|
|
111
|
+
id: update.id
|
|
112
|
+
}, {
|
|
113
|
+
value: update.value,
|
|
114
|
+
isVerified: update.isVerified ?? false
|
|
115
|
+
});
|
|
116
|
+
resultIds.push(update.id);
|
|
117
|
+
} else {
|
|
118
|
+
// Create new translation
|
|
119
|
+
const newTranslation = queryRunner.manager.create(Translation, {
|
|
120
|
+
languageId: update.languageId,
|
|
121
|
+
translationKeyId: update.translationKeyId,
|
|
122
|
+
value: update.value,
|
|
123
|
+
isVerified: update.isVerified ?? false,
|
|
124
|
+
isActive: true
|
|
125
|
+
});
|
|
126
|
+
const saved = await queryRunner.manager.save(newTranslation);
|
|
127
|
+
resultIds.push(saved.id);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
await queryRunner.commitTransaction();
|
|
131
|
+
return this.repository.find({
|
|
132
|
+
where: {
|
|
133
|
+
id: In(resultIds)
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
} catch (error) {
|
|
137
|
+
await queryRunner.rollbackTransaction();
|
|
138
|
+
throw error;
|
|
139
|
+
} finally{
|
|
140
|
+
await queryRunner.release();
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
async getMissingTranslations(languageCode) {
|
|
144
|
+
await this.ensureAllReposInitialized();
|
|
145
|
+
const language = await this.findActiveLanguageByCode(languageCode);
|
|
146
|
+
if (!language) return [];
|
|
147
|
+
if (!this.translationKeyRepo) return [];
|
|
148
|
+
const allKeys = await this.translationKeyRepo.find({
|
|
149
|
+
where: {
|
|
150
|
+
isActive: true,
|
|
151
|
+
deletedAt: IsNull()
|
|
152
|
+
}
|
|
153
|
+
});
|
|
154
|
+
const existingTranslations = await this.repository.find({
|
|
155
|
+
where: {
|
|
156
|
+
languageId: language.id,
|
|
157
|
+
isActive: true,
|
|
158
|
+
deletedAt: IsNull()
|
|
159
|
+
},
|
|
160
|
+
select: [
|
|
161
|
+
'translationKeyId'
|
|
162
|
+
]
|
|
163
|
+
});
|
|
164
|
+
const existingKeyIds = new Set(existingTranslations.map((t)=>t.translationKeyId));
|
|
165
|
+
return allKeys.filter((k)=>!existingKeyIds.has(k.id));
|
|
166
|
+
}
|
|
167
|
+
async getTranslationCounts() {
|
|
168
|
+
await this.ensureRepositoryInitialized();
|
|
169
|
+
const counts = await this.repository.createQueryBuilder('t').select('t.translation_key_id', 'keyId').addSelect('COUNT(t.id)', 'count').where('t.is_active = true').andWhere('t.deleted_at IS NULL').groupBy('t.translation_key_id').getRawMany();
|
|
170
|
+
const result = {};
|
|
171
|
+
for (const row of counts){
|
|
172
|
+
result[row.keyId] = parseInt(row.count, 10);
|
|
173
|
+
}
|
|
174
|
+
return result;
|
|
175
|
+
}
|
|
176
|
+
async findActiveLanguageByCode(code) {
|
|
177
|
+
if (!this.languageRepo) return null;
|
|
178
|
+
return this.languageRepo.findOne({
|
|
179
|
+
where: {
|
|
180
|
+
code,
|
|
181
|
+
isActive: true,
|
|
182
|
+
deletedAt: IsNull()
|
|
183
|
+
}
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
toTranslationsMap(translations) {
|
|
187
|
+
const result = {};
|
|
188
|
+
for (const t of translations){
|
|
189
|
+
if (t.translationKey) {
|
|
190
|
+
result[t.translationKey.key] = t.value;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
return result;
|
|
194
|
+
}
|
|
195
|
+
constructor(cacheManager, utilsService, dataSourceProvider){
|
|
196
|
+
super('translation', null, cacheManager, utilsService, TranslationService.name, true, 'localization'), _define_property(this, "cacheManager", void 0), _define_property(this, "utilsService", void 0), _define_property(this, "dataSourceProvider", void 0), _define_property(this, "languageRepo", void 0), _define_property(this, "translationKeyRepo", void 0), this.cacheManager = cacheManager, this.utilsService = utilsService, this.dataSourceProvider = dataSourceProvider, this.languageRepo = null, this.translationKeyRepo = null;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
TranslationService = _ts_decorate([
|
|
200
|
+
Injectable({
|
|
201
|
+
scope: Scope.REQUEST
|
|
202
|
+
}),
|
|
203
|
+
_ts_param(0, Inject('CACHE_INSTANCE')),
|
|
204
|
+
_ts_param(1, Inject(UtilsService)),
|
|
205
|
+
_ts_param(2, Inject(LocalizationDataSourceProvider)),
|
|
206
|
+
_ts_metadata("design:type", Function),
|
|
207
|
+
_ts_metadata("design:paramtypes", [
|
|
208
|
+
typeof HybridCache === "undefined" ? Object : HybridCache,
|
|
209
|
+
typeof UtilsService === "undefined" ? Object : UtilsService,
|
|
210
|
+
typeof LocalizationDataSourceProvider === "undefined" ? Object : LocalizationDataSourceProvider
|
|
211
|
+
])
|
|
212
|
+
], TranslationService);
|
package/index.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { IIdentity } from '@flusys/nestjs-shared/interfaces';
|
|
2
|
+
export interface ILanguage extends IIdentity {
|
|
3
|
+
code: string;
|
|
4
|
+
name: string;
|
|
5
|
+
nativeName: string | null;
|
|
6
|
+
direction: 'ltr' | 'rtl' | null;
|
|
7
|
+
isActive: boolean;
|
|
8
|
+
isDefault: boolean;
|
|
9
|
+
serial: number | null;
|
|
10
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { IBootstrapAppConfig, IDataSourceServiceOptions, IDynamicModuleConfig, IModuleOptionsFactory } from '@flusys/nestjs-core';
|
|
2
|
+
import { ModuleMetadata, Type } from '@nestjs/common';
|
|
3
|
+
export interface ILocalizationModuleConfig extends IDataSourceServiceOptions {
|
|
4
|
+
defaultLanguageCode?: string;
|
|
5
|
+
enableCaching?: boolean;
|
|
6
|
+
cacheTtlSeconds?: number;
|
|
7
|
+
}
|
|
8
|
+
export interface LocalizationModuleOptions extends IDynamicModuleConfig {
|
|
9
|
+
bootstrapAppConfig?: IBootstrapAppConfig;
|
|
10
|
+
config?: ILocalizationModuleConfig;
|
|
11
|
+
}
|
|
12
|
+
export interface LocalizationOptionsFactory extends IModuleOptionsFactory<ILocalizationModuleConfig> {
|
|
13
|
+
createLocalizationOptions(): Promise<ILocalizationModuleConfig> | ILocalizationModuleConfig;
|
|
14
|
+
}
|
|
15
|
+
export interface LocalizationModuleAsyncOptions extends Pick<ModuleMetadata, 'imports'>, IDynamicModuleConfig {
|
|
16
|
+
bootstrapAppConfig: IBootstrapAppConfig;
|
|
17
|
+
useFactory?: (...args: any[]) => Promise<ILocalizationModuleConfig> | ILocalizationModuleConfig;
|
|
18
|
+
inject?: any[];
|
|
19
|
+
useClass?: Type<LocalizationOptionsFactory>;
|
|
20
|
+
useExisting?: Type<LocalizationOptionsFactory>;
|
|
21
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { IIdentity } from '@flusys/nestjs-shared/interfaces';
|
|
2
|
+
export interface ITranslationKey extends IIdentity {
|
|
3
|
+
module: string;
|
|
4
|
+
key: string;
|
|
5
|
+
defaultMessage: string;
|
|
6
|
+
description: string | null;
|
|
7
|
+
variables: string[] | null;
|
|
8
|
+
isActive: boolean;
|
|
9
|
+
isReadonly: boolean;
|
|
10
|
+
serial: number | null;
|
|
11
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { IIdentity } from '@flusys/nestjs-shared/interfaces';
|
|
2
|
+
import { ILanguage } from './language.interface';
|
|
3
|
+
import { ITranslationKey } from './translation-key.interface';
|
|
4
|
+
export interface ITranslation extends IIdentity {
|
|
5
|
+
languageId: string;
|
|
6
|
+
translationKeyId: string;
|
|
7
|
+
value: string;
|
|
8
|
+
isVerified: boolean;
|
|
9
|
+
isActive: boolean;
|
|
10
|
+
language?: ILanguage;
|
|
11
|
+
translationKey?: ITranslationKey;
|
|
12
|
+
}
|
|
13
|
+
export type ITranslationsMap = Record<string, string>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './localization.module';
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { DynamicModule } from '@nestjs/common';
|
|
2
|
+
import { LocalizationModuleAsyncOptions, LocalizationModuleOptions } from '../interfaces';
|
|
3
|
+
export declare class LocalizationModule {
|
|
4
|
+
static forRoot(options: LocalizationModuleOptions): DynamicModule;
|
|
5
|
+
static forRootAsync(options: LocalizationModuleAsyncOptions): DynamicModule;
|
|
6
|
+
private static buildProviders;
|
|
7
|
+
private static createAsyncProviders;
|
|
8
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@flusys/nestjs-localization",
|
|
3
|
+
"version": "4.0.0-rc",
|
|
4
|
+
"description": "Localization module for multi-language support",
|
|
5
|
+
"main": "cjs/index.js",
|
|
6
|
+
"module": "fesm/index.js",
|
|
7
|
+
"types": "index.d.ts",
|
|
8
|
+
"sideEffects": false,
|
|
9
|
+
"keywords": [
|
|
10
|
+
"nestjs",
|
|
11
|
+
"localization",
|
|
12
|
+
"i18n",
|
|
13
|
+
"translation",
|
|
14
|
+
"multi-language",
|
|
15
|
+
"@flusys"
|
|
16
|
+
],
|
|
17
|
+
"license": "UNLICENSED",
|
|
18
|
+
"exports": {
|
|
19
|
+
".": {
|
|
20
|
+
"types": "./index.d.ts",
|
|
21
|
+
"import": "./fesm/index.js",
|
|
22
|
+
"require": "./cjs/index.js"
|
|
23
|
+
},
|
|
24
|
+
"./config": {
|
|
25
|
+
"types": "./config/index.d.ts",
|
|
26
|
+
"import": "./fesm/config/index.js",
|
|
27
|
+
"require": "./cjs/config/index.js"
|
|
28
|
+
},
|
|
29
|
+
"./controllers": {
|
|
30
|
+
"types": "./controllers/index.d.ts",
|
|
31
|
+
"import": "./fesm/controllers/index.js",
|
|
32
|
+
"require": "./cjs/controllers/index.js"
|
|
33
|
+
},
|
|
34
|
+
"./dtos": {
|
|
35
|
+
"types": "./dtos/index.d.ts",
|
|
36
|
+
"import": "./fesm/dtos/index.js",
|
|
37
|
+
"require": "./cjs/dtos/index.js"
|
|
38
|
+
},
|
|
39
|
+
"./entities": {
|
|
40
|
+
"types": "./entities/index.d.ts",
|
|
41
|
+
"import": "./fesm/entities/index.js",
|
|
42
|
+
"require": "./cjs/entities/index.js"
|
|
43
|
+
},
|
|
44
|
+
"./interfaces": {
|
|
45
|
+
"types": "./interfaces/index.d.ts",
|
|
46
|
+
"import": "./fesm/interfaces/index.js",
|
|
47
|
+
"require": "./cjs/interfaces/index.js"
|
|
48
|
+
},
|
|
49
|
+
"./modules": {
|
|
50
|
+
"types": "./modules/index.d.ts",
|
|
51
|
+
"import": "./fesm/modules/index.js",
|
|
52
|
+
"require": "./cjs/modules/index.js"
|
|
53
|
+
},
|
|
54
|
+
"./services": {
|
|
55
|
+
"types": "./services/index.d.ts",
|
|
56
|
+
"import": "./fesm/services/index.js",
|
|
57
|
+
"require": "./cjs/services/index.js"
|
|
58
|
+
},
|
|
59
|
+
"./*": {
|
|
60
|
+
"types": "./*.d.ts",
|
|
61
|
+
"import": "./*.js",
|
|
62
|
+
"require": "./*.js"
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
"peerDependencies": {
|
|
66
|
+
"@nestjs/common": "^10.0.0 || ^11.0.0",
|
|
67
|
+
"@nestjs/config": "^3.0.0 || ^4.0.0",
|
|
68
|
+
"@nestjs/core": "^10.0.0 || ^11.0.0",
|
|
69
|
+
"@nestjs/platform-express": "^10.0.0 || ^11.0.0",
|
|
70
|
+
"@nestjs/swagger": "^7.0.0 || ^11.0.0",
|
|
71
|
+
"@nestjs/typeorm": "^10.0.0 || ^11.0.0",
|
|
72
|
+
"class-transformer": "^0.5.0",
|
|
73
|
+
"class-validator": "^0.14.0",
|
|
74
|
+
"typeorm": "^0.3.0"
|
|
75
|
+
},
|
|
76
|
+
"dependencies": {
|
|
77
|
+
"@flusys/nestjs-core": "4.0.0-rc",
|
|
78
|
+
"@flusys/nestjs-shared": "4.0.0-rc"
|
|
79
|
+
}
|
|
80
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { HybridCache, RequestScopedApiService } from '@flusys/nestjs-shared/classes';
|
|
2
|
+
import { UtilsService } from '@flusys/nestjs-shared/modules';
|
|
3
|
+
import { EntityTarget, Repository } from 'typeorm';
|
|
4
|
+
import { CreateLanguageDto, UpdateLanguageDto } from '../dtos';
|
|
5
|
+
import { Language } from '../entities';
|
|
6
|
+
import { ILanguage } from '../interfaces';
|
|
7
|
+
import { LocalizationDataSourceProvider } from './localization-datasource.provider';
|
|
8
|
+
export declare class LanguageService extends RequestScopedApiService<CreateLanguageDto, UpdateLanguageDto, ILanguage, Language, Repository<Language>> {
|
|
9
|
+
protected cacheManager: HybridCache;
|
|
10
|
+
protected utilsService: UtilsService;
|
|
11
|
+
private readonly dataSourceProvider;
|
|
12
|
+
constructor(cacheManager: HybridCache, utilsService: UtilsService, dataSourceProvider: LocalizationDataSourceProvider);
|
|
13
|
+
protected resolveEntity(): EntityTarget<Language>;
|
|
14
|
+
protected getDataSourceProvider(): LocalizationDataSourceProvider;
|
|
15
|
+
getDefaultLanguage(): Promise<Language | null>;
|
|
16
|
+
getActiveLanguages(): Promise<Language[]>;
|
|
17
|
+
setAsDefault(id: string): Promise<Language | null>;
|
|
18
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { DatabaseMode } from '@flusys/nestjs-core';
|
|
2
|
+
import { IModuleConfigService } from '@flusys/nestjs-shared/interfaces';
|
|
3
|
+
import { LocalizationModuleOptions } from '../interfaces';
|
|
4
|
+
export declare class LocalizationConfigService implements IModuleConfigService {
|
|
5
|
+
private readonly options;
|
|
6
|
+
constructor(options: LocalizationModuleOptions);
|
|
7
|
+
isCompanyFeatureEnabled(): boolean;
|
|
8
|
+
getDatabaseMode(): DatabaseMode;
|
|
9
|
+
isMultiTenant(): boolean;
|
|
10
|
+
getOptions(): LocalizationModuleOptions;
|
|
11
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { MultiTenantDataSourceService } from '@flusys/nestjs-shared/modules';
|
|
2
|
+
import { IDatabaseConfig, ITenantDatabaseConfig } from '@flusys/nestjs-core';
|
|
3
|
+
import { Request } from 'express';
|
|
4
|
+
import { DataSource } from 'typeorm';
|
|
5
|
+
import { LocalizationConfigService } from './localization-config.service';
|
|
6
|
+
export declare class LocalizationDataSourceProvider extends MultiTenantDataSourceService {
|
|
7
|
+
protected static readonly tenantConnections: Map<string, DataSource>;
|
|
8
|
+
protected static singleDataSource: DataSource | null;
|
|
9
|
+
protected static readonly connectionLocks: Map<string, Promise<DataSource>>;
|
|
10
|
+
protected static singleConnectionLock: Promise<DataSource> | null;
|
|
11
|
+
constructor(configService: LocalizationConfigService, request?: Request);
|
|
12
|
+
private static buildParentOptions;
|
|
13
|
+
protected createDataSourceFromConfig(config: IDatabaseConfig): Promise<DataSource>;
|
|
14
|
+
protected getSingleDataSource(): Promise<DataSource>;
|
|
15
|
+
protected getOrCreateTenantConnection(tenant: ITenantDatabaseConfig): Promise<DataSource>;
|
|
16
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { HybridCache, RequestScopedApiService } from '@flusys/nestjs-shared/classes';
|
|
2
|
+
import { DeleteDto } from '@flusys/nestjs-shared/dtos';
|
|
3
|
+
import { ILoggedUserInfo } from '@flusys/nestjs-shared/interfaces';
|
|
4
|
+
import { UtilsService } from '@flusys/nestjs-shared/modules';
|
|
5
|
+
import { EntityTarget, QueryRunner, Repository } from 'typeorm';
|
|
6
|
+
import { CreateTranslationKeyDto, UpdateTranslationKeyDto } from '../dtos';
|
|
7
|
+
import { TranslationKey } from '../entities';
|
|
8
|
+
import { ITranslationKey } from '../interfaces';
|
|
9
|
+
import { LocalizationDataSourceProvider } from './localization-datasource.provider';
|
|
10
|
+
export declare class TranslationKeyService extends RequestScopedApiService<CreateTranslationKeyDto, UpdateTranslationKeyDto, ITranslationKey, TranslationKey, Repository<TranslationKey>> {
|
|
11
|
+
protected cacheManager: HybridCache;
|
|
12
|
+
protected utilsService: UtilsService;
|
|
13
|
+
private readonly dataSourceProvider;
|
|
14
|
+
constructor(cacheManager: HybridCache, utilsService: UtilsService, dataSourceProvider: LocalizationDataSourceProvider);
|
|
15
|
+
protected resolveEntity(): EntityTarget<TranslationKey>;
|
|
16
|
+
protected getDataSourceProvider(): LocalizationDataSourceProvider;
|
|
17
|
+
protected beforeInsertOperation(dto: CreateTranslationKeyDto | CreateTranslationKeyDto[], _user: ILoggedUserInfo | null, _queryRunner: QueryRunner): Promise<void>;
|
|
18
|
+
protected beforeUpdateOperation(dto: UpdateTranslationKeyDto | UpdateTranslationKeyDto[], _user: ILoggedUserInfo | null, _queryRunner: QueryRunner): Promise<void>;
|
|
19
|
+
protected beforeDeleteOperation(option: DeleteDto, _user: ILoggedUserInfo | null, _queryRunner: QueryRunner): Promise<void>;
|
|
20
|
+
findByModule(module: string): Promise<TranslationKey[]>;
|
|
21
|
+
getModules(): Promise<string[]>;
|
|
22
|
+
private validateNoDuplicateKeys;
|
|
23
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { HybridCache, RequestScopedApiService } from '@flusys/nestjs-shared/classes';
|
|
2
|
+
import { ILoggedUserInfo } from '@flusys/nestjs-shared/interfaces';
|
|
3
|
+
import { UtilsService } from '@flusys/nestjs-shared/modules';
|
|
4
|
+
import { EntityTarget, Repository, SelectQueryBuilder } from 'typeorm';
|
|
5
|
+
import { CreateTranslationDto, UpdateTranslationDto, BulkUpdateTranslationDto } from '../dtos';
|
|
6
|
+
import { Translation, TranslationKey } from '../entities';
|
|
7
|
+
import { ITranslation, ITranslationsMap } from '../interfaces';
|
|
8
|
+
import { LocalizationDataSourceProvider } from './localization-datasource.provider';
|
|
9
|
+
export declare class TranslationService extends RequestScopedApiService<CreateTranslationDto, UpdateTranslationDto, ITranslation, Translation, Repository<Translation>> {
|
|
10
|
+
protected cacheManager: HybridCache;
|
|
11
|
+
protected utilsService: UtilsService;
|
|
12
|
+
private readonly dataSourceProvider;
|
|
13
|
+
private languageRepo;
|
|
14
|
+
private translationKeyRepo;
|
|
15
|
+
constructor(cacheManager: HybridCache, utilsService: UtilsService, dataSourceProvider: LocalizationDataSourceProvider);
|
|
16
|
+
protected resolveEntity(): EntityTarget<Translation>;
|
|
17
|
+
protected getDataSourceProvider(): LocalizationDataSourceProvider;
|
|
18
|
+
protected getFilterQuery(query: SelectQueryBuilder<Translation>, filter: Record<string, unknown>, _user: ILoggedUserInfo | null): Promise<{
|
|
19
|
+
query: SelectQueryBuilder<Translation>;
|
|
20
|
+
isRaw: boolean;
|
|
21
|
+
}>;
|
|
22
|
+
private ensureAllReposInitialized;
|
|
23
|
+
getByLanguageCode(languageCode: string, modules?: string[]): Promise<ITranslationsMap>;
|
|
24
|
+
getByModuleAndLanguage(module: string, languageCode: string): Promise<ITranslationsMap>;
|
|
25
|
+
bulkUpdate(updates: BulkUpdateTranslationDto[]): Promise<Translation[]>;
|
|
26
|
+
getMissingTranslations(languageCode: string): Promise<TranslationKey[]>;
|
|
27
|
+
getTranslationCounts(): Promise<Record<string, number>>;
|
|
28
|
+
private findActiveLanguageByCode;
|
|
29
|
+
private toTranslationsMap;
|
|
30
|
+
}
|