feature: localization's first implmentation

This commit is contained in:
2026-06-20 12:37:38 +03:30
parent b314a5fa11
commit 284fbd08aa
46 changed files with 1860 additions and 643 deletions

View File

@@ -0,0 +1,2 @@
-- AlterTable
ALTER TABLE "users" ADD COLUMN "language" TEXT NOT NULL DEFAULT 'en';

View File

@@ -15,6 +15,7 @@ model User {
googleId String? @unique
facebookId String? @unique
name String
language String @default("en")
trialUsedAt DateTime?
memberships Membership[]

View File

@@ -9,7 +9,8 @@ import {
Res,
HttpCode,
HttpStatus,
Get
Get,
Patch,
} from '@nestjs/common';
import type { Response } from 'express';
import {
@@ -28,6 +29,7 @@ import { RegisterDto } from './dto/register.dto';
import { CreateOrganizationDto } from './dto/create-organization.dto';
import { JwtAuthGuard } from './guards/jwt-auth.guard';
import { LocalAuthGuard } from './guards/local-auth.guard';
import { UpdateLanguageDto } from './dto/update-language.dto';
@ApiTags('auth')
@Controller('auth')
@@ -149,6 +151,14 @@ export class AuthController {
return this.authService.getProfile(req.user.id);
}
@Patch('profile/language')
@UseGuards(JwtAuthGuard)
@ApiBearerAuth('JWT-auth')
@ApiOperation({ summary: 'Update user language preference' })
async updateLanguage(@Req() req, @Body() dto: UpdateLanguageDto) {
return this.authService.updateLanguage(req.user.id, dto);
}
@Get('subscription-alert')
@UseGuards(JwtAuthGuard)
@ApiBearerAuth('JWT-auth')

View File

@@ -15,6 +15,10 @@ import { PrismaService } from '../../../prisma/prisma.service';
import { LoginDto } from './dto/login.dto';
import { RegisterDto } from './dto/register.dto';
import { CreateOrganizationDto } from './dto/create-organization.dto';
import {
SUPPORTED_USER_LANGUAGES,
UpdateLanguageDto,
} from './dto/update-language.dto';
import { JwtPayload } from './interfaces/jwt-payload.interface';
const ALL_PERMISSIONS = [
@@ -179,11 +183,7 @@ export class AuthService {
data: {
accessToken,
refreshToken,
user: {
id: user.id,
email: user.email,
name: user.name,
},
user: this.toPublicUser(user),
organizations,
},
};
@@ -343,11 +343,6 @@ export class AuthService {
};
}
/**
* Get user profile with all memberships and permissions
* @param userId - User ID from JWT token
* @returns User profile with organizations and permissions
*/
async getProfile(userId: string) {
try {
const user = await this.prisma.user.findUnique({
@@ -516,11 +511,7 @@ export class AuthService {
success: true,
data: {
accessToken: newAccessToken,
user: {
id: session.user.id,
email: session.user.email,
name: session.user.name,
},
user: this.toPublicUser(session.user),
organizations,
},
};
@@ -931,4 +922,44 @@ export class AuthService {
},
};
}
async updateLanguage(userId: string, dto: UpdateLanguageDto) {
const language = dto.language;
if (!SUPPORTED_USER_LANGUAGES.includes(language)) {
throw new BadRequestException('Language must be one of: en, fa, nl');
}
const user = await this.prisma.user.update({
where: { id: userId },
data: { language },
select: {
id: true,
email: true,
name: true,
language: true,
},
});
return {
success: true,
data: {
user: this.toPublicUser(user),
},
};
}
private toPublicUser(user: {
id: string;
email: string;
name: string;
language?: string | null;
}) {
return {
id: user.id,
email: user.email,
name: user.name,
language: user.language ?? 'en',
};
}
}

View File

@@ -0,0 +1,14 @@
import { ApiProperty } from '@nestjs/swagger';
import { IsIn, IsString } from 'class-validator';
export const SUPPORTED_USER_LANGUAGES = ['en', 'fa', 'nl'] as const;
export type SupportedUserLanguage = (typeof SUPPORTED_USER_LANGUAGES)[number];
export class UpdateLanguageDto {
@ApiProperty({ enum: SUPPORTED_USER_LANGUAGES, example: 'en' })
@IsString()
@IsIn(SUPPORTED_USER_LANGUAGES, {
message: 'Language must be one of: en, fa, nl',
})
language: SupportedUserLanguage;
}