Skip to content

Commit

Permalink
add i18n for multi language purpose
Browse files Browse the repository at this point in the history
  • Loading branch information
bahram1249 committed May 6, 2024
1 parent 05dab08 commit 5a156a2
Show file tree
Hide file tree
Showing 10 changed files with 179 additions and 29 deletions.
8 changes: 7 additions & 1 deletion apps/e-commerce/src/guarantee/dto/guarantee.dto.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { ApiProperty } from '@nestjs/swagger';
import { replaceCharacterSlug } from '@rahino/commontools';
import { I18nTranslations } from 'apps/main/src/generated/i18n.generated';
import { AutoMap } from 'automapper-classes';
import { Transform } from 'class-transformer';
import {
Expand All @@ -9,11 +10,16 @@ import {
MaxLength,
MinLength,
} from 'class-validator';
import { i18nValidationMessage } from 'nestjs-i18n';

export class GuaranteeDto {
@MinLength(3)
@MaxLength(256)
@IsNotEmpty()
@IsNotEmpty({
message: i18nValidationMessage<I18nTranslations>(
'core.validation.is_not_empty',
),
})
@AutoMap()
name: string;

Expand Down
45 changes: 37 additions & 8 deletions apps/e-commerce/src/guarantee/guarantee.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ import * as fs from 'fs';
import { User } from '@rahino/database/models/core/user.entity';
import { MinioClientService } from '@rahino/minio-client';
import { ThumbnailService } from '@rahino/thumbnail';
import { I18nContext, I18nService } from 'nestjs-i18n';
import { I18nTranslations } from 'apps/main/src/generated/i18n.generated';

@Injectable()
export class GuaranteeService {
Expand All @@ -29,6 +31,7 @@ export class GuaranteeService {
@InjectMapper()
private readonly mapper: Mapper,
private readonly thumbnailService: ThumbnailService,
private readonly i18n: I18nService<I18nTranslations>,
) {}

async findAll(filter: GetGuaranteeDto) {
Expand Down Expand Up @@ -108,7 +111,11 @@ export class GuaranteeService {
.build(),
);
if (!guarantee) {
throw new NotFoundException('the item with this given id not founded!');
throw new NotFoundException(
this.i18n.t('core.not_found_id', {
lang: I18nContext.current().lang,
}),
);
}
return {
result: guarantee,
Expand All @@ -131,7 +138,9 @@ export class GuaranteeService {
);
if (item) {
throw new BadRequestException(
'the item with this slug is exists before !',
this.i18n.translate('core.the_given_slug_is_exists_before', {
lang: I18nContext.current().lang,
}),
);
}

Expand Down Expand Up @@ -167,7 +176,11 @@ export class GuaranteeService {
.build(),
);
if (!item) {
throw new NotFoundException('the item with this given id not founded!');
throw new NotFoundException(
this.i18n.t('core.not_found_id', {
lang: I18nContext.current().lang,
}),
);
}
const searchSlug = await this.repository.findOne(
new QueryOptionsBuilder()
Expand All @@ -189,7 +202,9 @@ export class GuaranteeService {
);
if (searchSlug) {
throw new BadRequestException(
'the item with this slug is exists before !',
this.i18n.t('core.the_given_slug_is_exists_before', {
lang: I18nContext.current().lang,
}),
);
}
const mappedItem = this.mapper.map(dto, GuaranteeDto, ECGuarantee);
Expand Down Expand Up @@ -230,7 +245,11 @@ export class GuaranteeService {
.build(),
);
if (!item) {
throw new NotFoundException('the item with this given id not founded!');
throw new NotFoundException(
this.i18n.t('core.not_found_id', {
lang: I18nContext.current().lang,
}),
);
}
item.isDeleted = true;
await item.save();
Expand Down Expand Up @@ -262,7 +281,11 @@ export class GuaranteeService {
.build(),
);
if (!item) {
throw new NotFoundException('the item with this given slug not founded!');
throw new NotFoundException(
this.i18n.t('core.not_found_slug', {
lang: I18nContext.current().lang,
}),
);
}
return {
result: _.pick(item, [
Expand Down Expand Up @@ -293,7 +316,9 @@ export class GuaranteeService {
.build(),
);
if (!item) {
throw new NotFoundException('the item with this given id not founded!');
throw new NotFoundException(
this.i18n.t('core.not_found_id', { lang: I18nContext.current().lang }),
);
}

// upload to s3 cloud
Expand Down Expand Up @@ -373,7 +398,11 @@ export class GuaranteeService {
.build(),
);
if (!attachment) {
throw new ForbiddenException("You don't have access to this file!");
throw new ForbiddenException(
this.i18n.t('core.dont_access_to_this_file', {
lang: I18nContext.current().lang,
}),
);
}
const accessUrl = await this.minioClientService.generateDownloadUrl(
attachment.bucketName,
Expand Down
20 changes: 20 additions & 0 deletions apps/main/src/generated/i18n.generated.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/* DO NOT EDIT, file generated by nestjs-i18n */

/* eslint-disable */
/* prettier-ignore */
import { Path } from "nestjs-i18n";
/* prettier-ignore */
export type I18nTranslations = {
"core": {
"not_found_id": string;
"not_found_slug": string;
"the_given_slug_is_exists_before": string;
"dont_access_to_this_file": string;
"validation": {
"is_not_empty": string;
};
"success": string;
};
};
/* prettier-ignore */
export type I18nPath = Path<I18nTranslations>;
13 changes: 13 additions & 0 deletions apps/main/src/i18nResolver/AppLanguageResolver.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { ExecutionContext, Inject, Injectable, Scope } from '@nestjs/common';
import { I18nResolver } from 'nestjs-i18n';

@Injectable()
export class AppLanguageResolver implements I18nResolver {
constructor() {}

resolve(
context: ExecutionContext,
): Promise<string | string[] | undefined> | string | string[] | undefined {
return 'fa';
}
}
23 changes: 22 additions & 1 deletion apps/main/src/routes/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ import * as session from 'express-session';
import { DynamicProviderModule } from '../dynamic-provider/dynamic-provider.module';
import { ThrottlerBehindProxyGuard } from '@rahino/commontools/guard';
import { APP_GUARD } from '@nestjs/core';
import { AcceptLanguageResolver, I18nModule, QueryResolver } from 'nestjs-i18n';
import * as path from 'path';
import { AppLanguageResolver } from '../i18nResolver/AppLanguageResolver';

@Module({
imports: [
Expand Down Expand Up @@ -66,7 +69,25 @@ import { APP_GUARD } from '@nestjs/core';
CoreModule,
UIModule,
DynamicProviderModule.register(),

I18nModule.forRoot({
fallbackLanguage: 'en',
loaderOptions: {
path: [path.join(__dirname, '../../../i18n/')],
watch: true,
},
resolvers: [
AppLanguageResolver,
{
use: QueryResolver,
options: ['lang'],
},
AcceptLanguageResolver,
],
typesOutputPath: path.join(
__dirname,
'../../../apps/main/src/generated/i18n.generated.ts',
),
}),
DevtoolsModule.register({
http: process.env.NODE_ENV !== 'production',
}),
Expand Down
10 changes: 10 additions & 0 deletions i18n/en/core.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"not_found_id": "the item with this given id not founded !",
"not_found_slug": "the item with this given slug not founded !",
"the_given_slug_is_exists_before": "the item with this given slug is exists before",
"dont_access_to_this_file": "You don't have access to this file !",
"validation": {
"is_not_empty": "{property} couldn't be empty"
},
"success": "success"
}
9 changes: 9 additions & 0 deletions i18n/fa/core.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"not_found_id": "آیتم مورد نظر توسط شناسه ارسال شده یافت نشد",
"not_found_slug": "آیتم مورد نظر توسط جداکننده یا لینک مورد نظر یافت نشد",
"dont_access_to_this_file": "شما دسترسی به این فایل را ندارید",
"validation": {
"is_not_empty": "{property} نمیتواند خالی باشد"
},
"success": "با موفقیت انجام شد"
}
3 changes: 2 additions & 1 deletion nest-cli.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
"deleteOutDir": true,
"webpack": true,
"tsConfigPath": "apps/main/tsconfig.app.json",
"plugins": ["@nestjs/swagger/plugin"]
"plugins": ["@nestjs/swagger/plugin"],
"assets": [{ "include": "i18n/**/*", "watchAssets": true }]
},
"monorepo": true,
"root": "apps/main",
Expand Down
Loading

0 comments on commit 5a156a2

Please sign in to comment.