@flusys/nestjs-localization 7.1.0 → 8.0.0
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/config/index.d.ts +3 -3
- package/controllers/index.d.ts +3 -3
- package/controllers/language.controller.d.ts +4 -4
- package/controllers/translation-key.controller.d.ts +3 -3
- package/controllers/translation.controller.d.ts +4 -4
- package/docs/index.d.ts +1 -1
- package/docs/localization-swagger.config.d.ts +1 -1
- package/dtos/index.d.ts +3 -3
- package/dtos/translation.dto.d.ts +2 -2
- package/entities/index.d.ts +6 -6
- package/entities/language.entity.d.ts +1 -1
- package/entities/translation-key.entity.d.ts +1 -1
- package/entities/translation.entity.d.ts +2 -2
- package/fesm/349.js +1179 -0
- package/fesm/692.js +1205 -0
- package/fesm/config/index.js +101 -3
- package/fesm/controllers/index.js +15 -3
- package/fesm/docs/index.js +126 -1
- package/fesm/dtos/index.js +680 -3
- package/fesm/entities/index.js +405 -8
- package/fesm/index.js +257 -7
- package/fesm/interfaces/index.js +18 -4
- package/fesm/modules/index.js +152 -1
- package/fesm/runtime.js +85 -0
- package/fesm/services/index.js +15 -5
- package/index.d.ts +7 -7
- package/interfaces/index.d.ts +4 -4
- package/interfaces/language.interface.d.ts +1 -1
- package/interfaces/localization-module-options.interface.d.ts +3 -3
- package/interfaces/translation-key.interface.d.ts +1 -1
- package/interfaces/translation.interface.d.ts +3 -3
- package/modules/index.d.ts +1 -1
- package/modules/localization.module.d.ts +2 -2
- package/package.json +25 -34
- package/services/index.d.ts +5 -5
- package/services/language.service.d.ts +6 -6
- package/services/localization-config.service.d.ts +3 -3
- package/services/localization-datasource.provider.d.ts +3 -3
- package/services/translation-key.service.d.ts +6 -6
- package/services/translation.service.d.ts +5 -5
- package/cjs/config/event-actions.js +0 -33
- package/cjs/config/index.js +0 -20
- package/cjs/config/localization.constants.js +0 -11
- package/cjs/config/message-keys.js +0 -41
- package/cjs/controllers/index.js +0 -20
- package/cjs/controllers/language.controller.js +0 -188
- package/cjs/controllers/language.controller.spec.js +0 -154
- package/cjs/controllers/translation-key.controller.js +0 -135
- package/cjs/controllers/translation-key.controller.spec.js +0 -70
- package/cjs/controllers/translation.controller.js +0 -195
- package/cjs/controllers/translation.controller.spec.js +0 -169
- package/cjs/docs/index.js +0 -11
- package/cjs/docs/localization-swagger.config.js +0 -111
- package/cjs/docs/localization-swagger.config.spec.js +0 -30
- package/cjs/dtos/index.js +0 -20
- package/cjs/dtos/language.dto.js +0 -213
- package/cjs/dtos/translation-key.dto.js +0 -215
- package/cjs/dtos/translation.dto.js +0 -269
- package/cjs/entities/index.js +0 -42
- package/cjs/entities/index.spec.js +0 -18
- package/cjs/entities/language.entity.js +0 -126
- package/cjs/entities/translation-key.entity.js +0 -126
- package/cjs/entities/translation.entity.js +0 -120
- package/cjs/index.js +0 -24
- package/cjs/interfaces/index.js +0 -21
- package/cjs/interfaces/language.interface.js +0 -4
- package/cjs/interfaces/localization-module-options.interface.js +0 -4
- package/cjs/interfaces/translation-key.interface.js +0 -4
- package/cjs/interfaces/translation.interface.js +0 -4
- package/cjs/modules/index.js +0 -18
- package/cjs/modules/localization.module.js +0 -116
- package/cjs/modules/localization.module.spec.js +0 -132
- package/cjs/services/index.js +0 -22
- package/cjs/services/language.service.js +0 -181
- package/cjs/services/language.service.spec.js +0 -256
- package/cjs/services/localization-config.service.js +0 -66
- package/cjs/services/localization-config.service.spec.js +0 -80
- package/cjs/services/localization-datasource.provider.js +0 -79
- package/cjs/services/localization-datasource.provider.spec.js +0 -85
- package/cjs/services/translation-key.service.js +0 -179
- package/cjs/services/translation-key.service.spec.js +0 -303
- package/cjs/services/translation.service.js +0 -228
- package/cjs/services/translation.service.spec.js +0 -530
- package/fesm/config/event-actions.js +0 -12
- package/fesm/config/localization.constants.js +0 -1
- package/fesm/config/message-keys.js +0 -20
- package/fesm/controllers/language.controller.js +0 -178
- package/fesm/controllers/language.controller.spec.js +0 -150
- package/fesm/controllers/translation-key.controller.js +0 -125
- package/fesm/controllers/translation-key.controller.spec.js +0 -66
- package/fesm/controllers/translation.controller.js +0 -185
- package/fesm/controllers/translation.controller.spec.js +0 -165
- package/fesm/docs/localization-swagger.config.js +0 -101
- package/fesm/docs/localization-swagger.config.spec.js +0 -26
- package/fesm/dtos/language.dto.js +0 -192
- package/fesm/dtos/translation-key.dto.js +0 -194
- package/fesm/dtos/translation.dto.js +0 -239
- package/fesm/entities/index.spec.js +0 -14
- package/fesm/entities/language.entity.js +0 -116
- package/fesm/entities/translation-key.entity.js +0 -116
- package/fesm/entities/translation.entity.js +0 -110
- package/fesm/interfaces/language.interface.js +0 -1
- package/fesm/interfaces/localization-module-options.interface.js +0 -1
- package/fesm/interfaces/translation-key.interface.js +0 -1
- package/fesm/interfaces/translation.interface.js +0 -1
- package/fesm/modules/localization.module.js +0 -106
- package/fesm/modules/localization.module.spec.js +0 -128
- package/fesm/services/language.service.js +0 -171
- package/fesm/services/language.service.spec.js +0 -252
- package/fesm/services/localization-config.service.js +0 -56
- package/fesm/services/localization-config.service.spec.js +0 -76
- package/fesm/services/localization-datasource.provider.js +0 -69
- package/fesm/services/localization-datasource.provider.spec.js +0 -81
- package/fesm/services/translation-key.service.js +0 -169
- package/fesm/services/translation-key.service.spec.js +0 -299
- package/fesm/services/translation.service.js +0 -218
- package/fesm/services/translation.service.spec.js +0 -526
|
@@ -1,195 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", {
|
|
3
|
-
value: true
|
|
4
|
-
});
|
|
5
|
-
Object.defineProperty(exports, "TranslationController", {
|
|
6
|
-
enumerable: true,
|
|
7
|
-
get: function() {
|
|
8
|
-
return TranslationController;
|
|
9
|
-
}
|
|
10
|
-
});
|
|
11
|
-
const _classes = require("@flusys/nestjs-shared/classes");
|
|
12
|
-
const _decorators = require("@flusys/nestjs-shared/decorators");
|
|
13
|
-
const _guards = require("@flusys/nestjs-shared/guards");
|
|
14
|
-
const _interfaces = require("@flusys/nestjs-shared/interfaces");
|
|
15
|
-
const _common = require("@nestjs/common");
|
|
16
|
-
const _swagger = require("@nestjs/swagger");
|
|
17
|
-
const _config = require("../config");
|
|
18
|
-
const _dtos = require("../dtos");
|
|
19
|
-
const _services = require("../services");
|
|
20
|
-
function _define_property(obj, key, value) {
|
|
21
|
-
if (key in obj) {
|
|
22
|
-
Object.defineProperty(obj, key, {
|
|
23
|
-
value: value,
|
|
24
|
-
enumerable: true,
|
|
25
|
-
configurable: true,
|
|
26
|
-
writable: true
|
|
27
|
-
});
|
|
28
|
-
} else {
|
|
29
|
-
obj[key] = value;
|
|
30
|
-
}
|
|
31
|
-
return obj;
|
|
32
|
-
}
|
|
33
|
-
function _ts_decorate(decorators, target, key, desc) {
|
|
34
|
-
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
35
|
-
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
36
|
-
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;
|
|
37
|
-
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
38
|
-
}
|
|
39
|
-
function _ts_metadata(k, v) {
|
|
40
|
-
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
41
|
-
}
|
|
42
|
-
function _ts_param(paramIndex, decorator) {
|
|
43
|
-
return function(target, key) {
|
|
44
|
-
decorator(target, key, paramIndex);
|
|
45
|
-
};
|
|
46
|
-
}
|
|
47
|
-
let TranslationController = class TranslationController extends (0, _classes.createApiController)(_dtos.CreateTranslationDto, _dtos.UpdateTranslationDto, _dtos.TranslationResponseDto, {
|
|
48
|
-
entityName: 'translation',
|
|
49
|
-
security: {
|
|
50
|
-
insert: {
|
|
51
|
-
level: 'permission',
|
|
52
|
-
permissions: [
|
|
53
|
-
_classes.TRANSLATION_PERMISSIONS.CREATE
|
|
54
|
-
]
|
|
55
|
-
},
|
|
56
|
-
insertMany: {
|
|
57
|
-
level: 'permission',
|
|
58
|
-
permissions: [
|
|
59
|
-
_classes.TRANSLATION_PERMISSIONS.CREATE
|
|
60
|
-
]
|
|
61
|
-
},
|
|
62
|
-
getById: {
|
|
63
|
-
level: 'permission',
|
|
64
|
-
permissions: [
|
|
65
|
-
_classes.TRANSLATION_PERMISSIONS.READ
|
|
66
|
-
]
|
|
67
|
-
},
|
|
68
|
-
getAll: {
|
|
69
|
-
level: 'permission',
|
|
70
|
-
permissions: [
|
|
71
|
-
_classes.TRANSLATION_PERMISSIONS.READ
|
|
72
|
-
]
|
|
73
|
-
},
|
|
74
|
-
update: {
|
|
75
|
-
level: 'permission',
|
|
76
|
-
permissions: [
|
|
77
|
-
_classes.TRANSLATION_PERMISSIONS.UPDATE
|
|
78
|
-
]
|
|
79
|
-
},
|
|
80
|
-
updateMany: {
|
|
81
|
-
level: 'permission',
|
|
82
|
-
permissions: [
|
|
83
|
-
_classes.TRANSLATION_PERMISSIONS.UPDATE
|
|
84
|
-
]
|
|
85
|
-
},
|
|
86
|
-
delete: {
|
|
87
|
-
level: 'permission',
|
|
88
|
-
permissions: [
|
|
89
|
-
_classes.TRANSLATION_PERMISSIONS.DELETE
|
|
90
|
-
]
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
}) {
|
|
94
|
-
async getByLanguage(body) {
|
|
95
|
-
const data = await this.service.getByLanguageCode(body.languageCode, body.modules);
|
|
96
|
-
return {
|
|
97
|
-
success: true,
|
|
98
|
-
message: 'Translations retrieved successfully',
|
|
99
|
-
messageKey: _config.TRANSLATION_MESSAGES.BY_LANGUAGE_SUCCESS,
|
|
100
|
-
data
|
|
101
|
-
};
|
|
102
|
-
}
|
|
103
|
-
async updateManyValues(body, _user) {
|
|
104
|
-
const data = await this.service.bulkUpdate(body.translations);
|
|
105
|
-
return {
|
|
106
|
-
success: true,
|
|
107
|
-
message: `${data.length} translations updated`,
|
|
108
|
-
messageKey: _config.TRANSLATION_MESSAGES.UPDATE_MANY_SUCCESS,
|
|
109
|
-
messageVariables: {
|
|
110
|
-
count: data.length
|
|
111
|
-
},
|
|
112
|
-
data,
|
|
113
|
-
meta: {
|
|
114
|
-
count: data.length
|
|
115
|
-
}
|
|
116
|
-
};
|
|
117
|
-
}
|
|
118
|
-
async getCounts(_user) {
|
|
119
|
-
const data = await this.service.getTranslationCounts();
|
|
120
|
-
return {
|
|
121
|
-
success: true,
|
|
122
|
-
message: 'Translation counts retrieved successfully',
|
|
123
|
-
messageKey: _config.TRANSLATION_MESSAGES.GET_ALL_SUCCESS,
|
|
124
|
-
data
|
|
125
|
-
};
|
|
126
|
-
}
|
|
127
|
-
constructor(service){
|
|
128
|
-
super(service), _define_property(this, "service", void 0), this.service = service;
|
|
129
|
-
}
|
|
130
|
-
};
|
|
131
|
-
_ts_decorate([
|
|
132
|
-
(0, _common.Post)('get-by-language'),
|
|
133
|
-
(0, _swagger.ApiOperation)({
|
|
134
|
-
summary: 'Get translations for a language (optionally filtered by modules)'
|
|
135
|
-
}),
|
|
136
|
-
(0, _swagger.ApiResponse)({
|
|
137
|
-
status: 200
|
|
138
|
-
}),
|
|
139
|
-
_ts_param(0, (0, _common.Body)()),
|
|
140
|
-
_ts_metadata("design:type", Function),
|
|
141
|
-
_ts_metadata("design:paramtypes", [
|
|
142
|
-
typeof _dtos.GetTranslationsByLanguageDto === "undefined" ? Object : _dtos.GetTranslationsByLanguageDto
|
|
143
|
-
]),
|
|
144
|
-
_ts_metadata("design:returntype", Promise)
|
|
145
|
-
], TranslationController.prototype, "getByLanguage", null);
|
|
146
|
-
_ts_decorate([
|
|
147
|
-
(0, _common.Post)('update-many-values'),
|
|
148
|
-
(0, _common.UseGuards)(_guards.JwtAuthGuard, _guards.PermissionGuard),
|
|
149
|
-
(0, _swagger.ApiBearerAuth)(),
|
|
150
|
-
(0, _decorators.RequirePermission)(_classes.TRANSLATION_PERMISSIONS.UPDATE),
|
|
151
|
-
(0, _swagger.ApiOperation)({
|
|
152
|
-
summary: 'Bulk update translation values'
|
|
153
|
-
}),
|
|
154
|
-
(0, _swagger.ApiResponse)({
|
|
155
|
-
status: 200,
|
|
156
|
-
type: [
|
|
157
|
-
_dtos.TranslationResponseDto
|
|
158
|
-
]
|
|
159
|
-
}),
|
|
160
|
-
_ts_param(0, (0, _common.Body)()),
|
|
161
|
-
_ts_param(1, (0, _decorators.CurrentUser)()),
|
|
162
|
-
_ts_metadata("design:type", Function),
|
|
163
|
-
_ts_metadata("design:paramtypes", [
|
|
164
|
-
typeof _dtos.BulkUpdateTranslationsDto === "undefined" ? Object : _dtos.BulkUpdateTranslationsDto,
|
|
165
|
-
typeof _interfaces.ILoggedUserInfo === "undefined" ? Object : _interfaces.ILoggedUserInfo
|
|
166
|
-
]),
|
|
167
|
-
_ts_metadata("design:returntype", Promise)
|
|
168
|
-
], TranslationController.prototype, "updateManyValues", null);
|
|
169
|
-
_ts_decorate([
|
|
170
|
-
(0, _common.Post)('get-counts'),
|
|
171
|
-
(0, _common.UseGuards)(_guards.JwtAuthGuard, _guards.PermissionGuard),
|
|
172
|
-
(0, _swagger.ApiBearerAuth)(),
|
|
173
|
-
(0, _decorators.RequirePermission)(_classes.TRANSLATION_PERMISSIONS.READ),
|
|
174
|
-
(0, _swagger.ApiOperation)({
|
|
175
|
-
summary: 'Get translation counts per translation key'
|
|
176
|
-
}),
|
|
177
|
-
(0, _swagger.ApiResponse)({
|
|
178
|
-
status: 200
|
|
179
|
-
}),
|
|
180
|
-
_ts_param(0, (0, _decorators.CurrentUser)()),
|
|
181
|
-
_ts_metadata("design:type", Function),
|
|
182
|
-
_ts_metadata("design:paramtypes", [
|
|
183
|
-
typeof _interfaces.ILoggedUserInfo === "undefined" ? Object : _interfaces.ILoggedUserInfo
|
|
184
|
-
]),
|
|
185
|
-
_ts_metadata("design:returntype", Promise)
|
|
186
|
-
], TranslationController.prototype, "getCounts", null);
|
|
187
|
-
TranslationController = _ts_decorate([
|
|
188
|
-
(0, _swagger.ApiTags)('Localization - Translation'),
|
|
189
|
-
(0, _common.Controller)('localization/translation'),
|
|
190
|
-
_ts_param(0, (0, _common.Inject)(_services.TranslationService)),
|
|
191
|
-
_ts_metadata("design:type", Function),
|
|
192
|
-
_ts_metadata("design:paramtypes", [
|
|
193
|
-
typeof _services.TranslationService === "undefined" ? Object : _services.TranslationService
|
|
194
|
-
])
|
|
195
|
-
], TranslationController);
|
|
@@ -1,169 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", {
|
|
3
|
-
value: true
|
|
4
|
-
});
|
|
5
|
-
const _testing = require("@nestjs/testing");
|
|
6
|
-
const _modules = require("@flusys/nestjs-shared/modules");
|
|
7
|
-
const _loggedusermock = require("@test-utils/mocks/logged-user.mock");
|
|
8
|
-
const _translationcontroller = require("./translation.controller");
|
|
9
|
-
const _services = require("../services");
|
|
10
|
-
function buildTranslation(overrides = {}) {
|
|
11
|
-
return {
|
|
12
|
-
id: 'translation-1',
|
|
13
|
-
languageId: 'lang-en',
|
|
14
|
-
translationKeyId: 'tkey-1',
|
|
15
|
-
value: 'Login successful',
|
|
16
|
-
isVerified: false,
|
|
17
|
-
isActive: true,
|
|
18
|
-
createdAt: new Date(),
|
|
19
|
-
updatedAt: new Date(),
|
|
20
|
-
deletedAt: null,
|
|
21
|
-
createdById: null,
|
|
22
|
-
updatedById: null,
|
|
23
|
-
deletedById: null,
|
|
24
|
-
...overrides
|
|
25
|
-
};
|
|
26
|
-
}
|
|
27
|
-
describe('TranslationController', ()=>{
|
|
28
|
-
let controller;
|
|
29
|
-
let mockService;
|
|
30
|
-
beforeEach(async ()=>{
|
|
31
|
-
mockService = {
|
|
32
|
-
insert: jest.fn(),
|
|
33
|
-
findById: jest.fn(),
|
|
34
|
-
getAll: jest.fn(),
|
|
35
|
-
update: jest.fn(),
|
|
36
|
-
delete: jest.fn(),
|
|
37
|
-
getByLanguageCode: jest.fn(),
|
|
38
|
-
bulkUpdate: jest.fn(),
|
|
39
|
-
getTranslationCounts: jest.fn()
|
|
40
|
-
};
|
|
41
|
-
const module = await _testing.Test.createTestingModule({
|
|
42
|
-
controllers: [
|
|
43
|
-
_translationcontroller.TranslationController
|
|
44
|
-
],
|
|
45
|
-
providers: [
|
|
46
|
-
{
|
|
47
|
-
provide: _services.TranslationService,
|
|
48
|
-
useValue: mockService
|
|
49
|
-
},
|
|
50
|
-
{
|
|
51
|
-
provide: _modules.UtilsService,
|
|
52
|
-
useValue: {}
|
|
53
|
-
}
|
|
54
|
-
]
|
|
55
|
-
}).compile();
|
|
56
|
-
controller = module.get(_translationcontroller.TranslationController);
|
|
57
|
-
});
|
|
58
|
-
describe('getByLanguage', ()=>{
|
|
59
|
-
it('returns the translations map for the requested language and modules', async ()=>{
|
|
60
|
-
mockService.getByLanguageCode.mockResolvedValue({
|
|
61
|
-
'auth.login.success': 'Login successful'
|
|
62
|
-
});
|
|
63
|
-
const result = await controller.getByLanguage({
|
|
64
|
-
languageCode: 'en',
|
|
65
|
-
modules: [
|
|
66
|
-
'auth'
|
|
67
|
-
]
|
|
68
|
-
});
|
|
69
|
-
expect(mockService.getByLanguageCode).toHaveBeenCalledWith('en', [
|
|
70
|
-
'auth'
|
|
71
|
-
]);
|
|
72
|
-
expect(result).toEqual({
|
|
73
|
-
success: true,
|
|
74
|
-
message: 'Translations retrieved successfully',
|
|
75
|
-
messageKey: 'translation.by.language.success',
|
|
76
|
-
data: {
|
|
77
|
-
'auth.login.success': 'Login successful'
|
|
78
|
-
}
|
|
79
|
-
});
|
|
80
|
-
});
|
|
81
|
-
it('returns an empty map (fallback) for an unknown language code without throwing', async ()=>{
|
|
82
|
-
mockService.getByLanguageCode.mockResolvedValue({});
|
|
83
|
-
const result = await controller.getByLanguage({
|
|
84
|
-
languageCode: 'xx'
|
|
85
|
-
});
|
|
86
|
-
expect(result.success).toBe(true);
|
|
87
|
-
expect(result.data).toEqual({});
|
|
88
|
-
});
|
|
89
|
-
it('requests translations for all modules when modules is omitted', async ()=>{
|
|
90
|
-
mockService.getByLanguageCode.mockResolvedValue({});
|
|
91
|
-
await controller.getByLanguage({
|
|
92
|
-
languageCode: 'en'
|
|
93
|
-
});
|
|
94
|
-
expect(mockService.getByLanguageCode).toHaveBeenCalledWith('en', undefined);
|
|
95
|
-
});
|
|
96
|
-
});
|
|
97
|
-
describe('updateManyValues', ()=>{
|
|
98
|
-
it('bulk updates translations and reports the updated count', async ()=>{
|
|
99
|
-
const updated = [
|
|
100
|
-
buildTranslation(),
|
|
101
|
-
buildTranslation({
|
|
102
|
-
id: 'translation-2'
|
|
103
|
-
})
|
|
104
|
-
];
|
|
105
|
-
mockService.bulkUpdate.mockResolvedValue(updated);
|
|
106
|
-
const result = await controller.updateManyValues({
|
|
107
|
-
translations: [
|
|
108
|
-
{
|
|
109
|
-
languageId: 'lang-en',
|
|
110
|
-
translationKeyId: 'tkey-1',
|
|
111
|
-
value: 'Login successful'
|
|
112
|
-
}
|
|
113
|
-
]
|
|
114
|
-
}, (0, _loggedusermock.buildMockUser)());
|
|
115
|
-
expect(result).toEqual({
|
|
116
|
-
success: true,
|
|
117
|
-
message: '2 translations updated',
|
|
118
|
-
messageKey: 'translation.update.many.success',
|
|
119
|
-
messageVariables: {
|
|
120
|
-
count: 2
|
|
121
|
-
},
|
|
122
|
-
data: updated,
|
|
123
|
-
meta: {
|
|
124
|
-
count: 2
|
|
125
|
-
}
|
|
126
|
-
});
|
|
127
|
-
});
|
|
128
|
-
it('reports zero updates for an empty batch without calling the service twice', async ()=>{
|
|
129
|
-
mockService.bulkUpdate.mockResolvedValue([]);
|
|
130
|
-
const result = await controller.updateManyValues({
|
|
131
|
-
translations: []
|
|
132
|
-
}, (0, _loggedusermock.buildMockUser)());
|
|
133
|
-
expect(mockService.bulkUpdate).toHaveBeenCalledTimes(1);
|
|
134
|
-
expect(result.meta).toEqual({
|
|
135
|
-
count: 0
|
|
136
|
-
});
|
|
137
|
-
expect(result.message).toBe('0 translations updated');
|
|
138
|
-
});
|
|
139
|
-
it('propagates errors raised during the bulk transaction (e.g. rollback surfaced as a rejection)', async ()=>{
|
|
140
|
-
mockService.bulkUpdate.mockRejectedValue(new Error('transaction rolled back'));
|
|
141
|
-
await expect(controller.updateManyValues({
|
|
142
|
-
translations: []
|
|
143
|
-
}, (0, _loggedusermock.buildMockUser)())).rejects.toThrow('transaction rolled back');
|
|
144
|
-
});
|
|
145
|
-
});
|
|
146
|
-
describe('getCounts', ()=>{
|
|
147
|
-
it('returns translation counts keyed by translation key id', async ()=>{
|
|
148
|
-
mockService.getTranslationCounts.mockResolvedValue({
|
|
149
|
-
'tkey-1': 3,
|
|
150
|
-
'tkey-2': 1
|
|
151
|
-
});
|
|
152
|
-
const result = await controller.getCounts((0, _loggedusermock.buildMockUser)());
|
|
153
|
-
expect(result).toEqual({
|
|
154
|
-
success: true,
|
|
155
|
-
message: 'Translation counts retrieved successfully',
|
|
156
|
-
messageKey: 'translation.get.all.success',
|
|
157
|
-
data: {
|
|
158
|
-
'tkey-1': 3,
|
|
159
|
-
'tkey-2': 1
|
|
160
|
-
}
|
|
161
|
-
});
|
|
162
|
-
});
|
|
163
|
-
it('returns an empty object when there are no translations yet', async ()=>{
|
|
164
|
-
mockService.getTranslationCounts.mockResolvedValue({});
|
|
165
|
-
const result = await controller.getCounts((0, _loggedusermock.buildMockUser)());
|
|
166
|
-
expect(result.data).toEqual({});
|
|
167
|
-
});
|
|
168
|
-
});
|
|
169
|
-
});
|
package/cjs/docs/index.js
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", {
|
|
3
|
-
value: true
|
|
4
|
-
});
|
|
5
|
-
Object.defineProperty(exports, "localizationSwaggerConfig", {
|
|
6
|
-
enumerable: true,
|
|
7
|
-
get: function() {
|
|
8
|
-
return _localizationswaggerconfig.localizationSwaggerConfig;
|
|
9
|
-
}
|
|
10
|
-
});
|
|
11
|
-
const _localizationswaggerconfig = require("./localization-swagger.config");
|
|
@@ -1,111 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", {
|
|
3
|
-
value: true
|
|
4
|
-
});
|
|
5
|
-
Object.defineProperty(exports, "localizationSwaggerConfig", {
|
|
6
|
-
enumerable: true,
|
|
7
|
-
get: function() {
|
|
8
|
-
return localizationSwaggerConfig;
|
|
9
|
-
}
|
|
10
|
-
});
|
|
11
|
-
function localizationSwaggerConfig(bootstrapConfig) {
|
|
12
|
-
const isMultiTenant = bootstrapConfig?.databaseMode === 'multi-tenant';
|
|
13
|
-
const multiTenantNote = isMultiTenant ? `\n> **Multi-Tenant Mode**: Include \`x-tenant-id\` header to target a specific tenant database.\n` : '';
|
|
14
|
-
return {
|
|
15
|
-
title: 'Localization API',
|
|
16
|
-
description: `
|
|
17
|
-
## Localization API
|
|
18
|
-
${multiTenantNote}
|
|
19
|
-
|
|
20
|
-
Database-driven internationalization system. Manage languages, translation keys, and translations — all stored in the database and served via API.
|
|
21
|
-
|
|
22
|
-
## Features
|
|
23
|
-
|
|
24
|
-
### 🌐 Language Management
|
|
25
|
-
- Create and manage languages with LTR/RTL direction support
|
|
26
|
-
- Set a default language
|
|
27
|
-
- Mark languages as readonly to protect seeded entries
|
|
28
|
-
|
|
29
|
-
### 🔑 Translation Keys
|
|
30
|
-
- Organize keys by module for lazy loading (e.g. \`auth\`, \`iam\`, \`common\`)
|
|
31
|
-
- Dot-case naming convention: \`auth.login.title\`, \`common.button.save\`
|
|
32
|
-
- Support for interpolation variables: \`['count', 'name']\`
|
|
33
|
-
- Readonly protection — system keys cannot be deleted or have their key/module changed
|
|
34
|
-
|
|
35
|
-
### 📝 Translations
|
|
36
|
-
- Store translated values per language per key
|
|
37
|
-
- Mark translations as verified
|
|
38
|
-
- Bulk upsert in a single transaction — create or update in one call
|
|
39
|
-
- Detect missing translations for a given language
|
|
40
|
-
- Track translation counts per key
|
|
41
|
-
|
|
42
|
-
### 🚀 Angular Lazy Loading
|
|
43
|
-
- Public endpoints return flat key-value maps: \`{ "auth.login.title": "Sign In" }\`
|
|
44
|
-
- Filter by one or multiple modules to load only what is needed
|
|
45
|
-
- No authentication required for translation retrieval endpoints
|
|
46
|
-
|
|
47
|
-
## Key Naming Convention
|
|
48
|
-
|
|
49
|
-
Translation keys use dot-case and must be unique per module:
|
|
50
|
-
|
|
51
|
-
\`\`\`
|
|
52
|
-
auth.login.title
|
|
53
|
-
auth.login.submit
|
|
54
|
-
auth.register.email.placeholder
|
|
55
|
-
common.button.save
|
|
56
|
-
common.button.cancel
|
|
57
|
-
iam.role.create.success
|
|
58
|
-
\`\`\`
|
|
59
|
-
|
|
60
|
-
## Module-Based Lazy Loading
|
|
61
|
-
|
|
62
|
-
Keys are grouped by \`module\` so the frontend loads translations on demand:
|
|
63
|
-
|
|
64
|
-
| Module | Purpose |
|
|
65
|
-
|--------|---------|
|
|
66
|
-
| auth | Login, register, profile pages |
|
|
67
|
-
| iam | Roles, permissions management |
|
|
68
|
-
| storage | Files and folders |
|
|
69
|
-
| event-manager | Calendar events |
|
|
70
|
-
| form-builder | Dynamic form fields |
|
|
71
|
-
| notification | Notification titles and messages |
|
|
72
|
-
| email | Email template content |
|
|
73
|
-
| common | Shared labels used across modules |
|
|
74
|
-
|
|
75
|
-
## Public vs Authenticated Endpoints
|
|
76
|
-
|
|
77
|
-
**Public** (no auth required — used by Angular to load translations):
|
|
78
|
-
- POST /localization/language/get-active
|
|
79
|
-
- POST /localization/language/get-default
|
|
80
|
-
- POST /localization/translation/get-by-language
|
|
81
|
-
- POST /localization/translation/get-by-module
|
|
82
|
-
|
|
83
|
-
**Authenticated** (require JWT + permission):
|
|
84
|
-
- All create, update, delete operations
|
|
85
|
-
- get-missing, get-counts, update-many-values
|
|
86
|
-
|
|
87
|
-
## Bulk Update
|
|
88
|
-
|
|
89
|
-
POST /localization/translation/update-many-values accepts an array of translation objects. Each item is either an upsert (provide **id** to update, omit to create). The entire batch runs in a single database transaction.
|
|
90
|
-
|
|
91
|
-
## Readonly Protection
|
|
92
|
-
|
|
93
|
-
Languages and translation keys with \`isReadonly: true\` are protected at the service layer:
|
|
94
|
-
- Cannot be deleted
|
|
95
|
-
- Key and module fields cannot be modified
|
|
96
|
-
|
|
97
|
-
Use \`isReadonly\` to protect entries that are seeded at startup and should not be changed by users.
|
|
98
|
-
|
|
99
|
-
## Getting Started
|
|
100
|
-
|
|
101
|
-
1. **Authenticate**: Obtain JWT token from POST /auth/login
|
|
102
|
-
2. **Create languages**: Add languages via POST /localization/language/insert
|
|
103
|
-
3. **Seed translation keys**: Bulk insert keys via POST /localization/translation-key/insert-many
|
|
104
|
-
4. **Add translations**: Use POST /localization/translation/update-many-values for bulk upsert
|
|
105
|
-
5. **Load in Angular**: Call POST /localization/translation/get-by-language with { languageCode: "en", modules: ["auth"] }
|
|
106
|
-
`,
|
|
107
|
-
version: '1.0',
|
|
108
|
-
path: 'api/docs/localization',
|
|
109
|
-
bearerAuth: true
|
|
110
|
-
};
|
|
111
|
-
}
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", {
|
|
3
|
-
value: true
|
|
4
|
-
});
|
|
5
|
-
const _localizationswaggerconfig = require("./localization-swagger.config");
|
|
6
|
-
describe('localizationSwaggerConfig', ()=>{
|
|
7
|
-
it('should build a static config with no multi-tenant note by default', ()=>{
|
|
8
|
-
const config = (0, _localizationswaggerconfig.localizationSwaggerConfig)();
|
|
9
|
-
expect(config.title).toBe('Localization API');
|
|
10
|
-
expect(config.path).toBe('api/docs/localization');
|
|
11
|
-
expect(config.bearerAuth).toBe(true);
|
|
12
|
-
expect(config.description).not.toContain('Multi-Tenant Mode');
|
|
13
|
-
});
|
|
14
|
-
it('should include the multi-tenant note only for multi-tenant database mode', ()=>{
|
|
15
|
-
const multiTenant = (0, _localizationswaggerconfig.localizationSwaggerConfig)({
|
|
16
|
-
databaseMode: 'multi-tenant'
|
|
17
|
-
});
|
|
18
|
-
const single = (0, _localizationswaggerconfig.localizationSwaggerConfig)({
|
|
19
|
-
databaseMode: 'single'
|
|
20
|
-
});
|
|
21
|
-
expect(multiTenant.description).toContain('Multi-Tenant Mode');
|
|
22
|
-
expect(single.description).not.toContain('Multi-Tenant Mode');
|
|
23
|
-
});
|
|
24
|
-
it('should treat any non-"multi-tenant" value as single-database mode', ()=>{
|
|
25
|
-
const config = (0, _localizationswaggerconfig.localizationSwaggerConfig)({
|
|
26
|
-
databaseMode: 'unexpected-value'
|
|
27
|
-
});
|
|
28
|
-
expect(config.description).not.toContain('Multi-Tenant Mode');
|
|
29
|
-
});
|
|
30
|
-
});
|
package/cjs/dtos/index.js
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", {
|
|
3
|
-
value: true
|
|
4
|
-
});
|
|
5
|
-
_export_star(require("./language.dto"), exports);
|
|
6
|
-
_export_star(require("./translation-key.dto"), exports);
|
|
7
|
-
_export_star(require("./translation.dto"), exports);
|
|
8
|
-
function _export_star(from, to) {
|
|
9
|
-
Object.keys(from).forEach(function(k) {
|
|
10
|
-
if (k !== "default" && !Object.prototype.hasOwnProperty.call(to, k)) {
|
|
11
|
-
Object.defineProperty(to, k, {
|
|
12
|
-
enumerable: true,
|
|
13
|
-
get: function() {
|
|
14
|
-
return from[k];
|
|
15
|
-
}
|
|
16
|
-
});
|
|
17
|
-
}
|
|
18
|
-
});
|
|
19
|
-
return from;
|
|
20
|
-
}
|