重构 API 为 8 领域 + 应用层架构
将后端模块拆分为 domains、applications、shared 三层,结算计算器移入 domain 纯函数目录,API 路径与测试保持不变。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
8
apps/api/src/domains/operations/i18n/i18n.module.ts
Normal file
8
apps/api/src/domains/operations/i18n/i18n.module.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { I18nService } from './i18n.service';
|
||||
|
||||
@Module({
|
||||
providers: [I18nService],
|
||||
exports: [I18nService],
|
||||
})
|
||||
export class I18nModule {}
|
||||
55
apps/api/src/domains/operations/i18n/i18n.service.ts
Normal file
55
apps/api/src/domains/operations/i18n/i18n.service.ts
Normal file
@@ -0,0 +1,55 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { PrismaService } from '../../../shared/prisma/prisma.service';
|
||||
import { DEFAULT_LOCALE } from '@thebet365/shared';
|
||||
|
||||
const FALLBACK_ORDER = ['en-US', 'zh-CN', 'ms-MY'];
|
||||
|
||||
@Injectable()
|
||||
export class I18nService {
|
||||
constructor(private prisma: PrismaService) {}
|
||||
|
||||
async getMessages(locale: string) {
|
||||
const messages = await this.prisma.i18nMessage.findMany({
|
||||
where: { locale: { in: [locale, ...FALLBACK_ORDER] } },
|
||||
});
|
||||
|
||||
const byKey: Record<string, Record<string, string>> = {};
|
||||
for (const m of messages) {
|
||||
if (!byKey[m.msgKey]) byKey[m.msgKey] = {};
|
||||
byKey[m.msgKey][m.locale] = m.value;
|
||||
}
|
||||
|
||||
const result: Record<string, string> = {};
|
||||
for (const [key, locales] of Object.entries(byKey)) {
|
||||
result[key] =
|
||||
locales[locale] ||
|
||||
FALLBACK_ORDER.map((l) => locales[l]).find(Boolean) ||
|
||||
key;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
async upsertMessage(msgKey: string, locale: string, value: string) {
|
||||
return this.prisma.i18nMessage.upsert({
|
||||
where: { msgKey_locale: { msgKey, locale } },
|
||||
create: { msgKey, locale, value },
|
||||
update: { value },
|
||||
});
|
||||
}
|
||||
|
||||
async listMissing() {
|
||||
const keys = await this.prisma.i18nMessage.groupBy({ by: ['msgKey'] });
|
||||
const locales = ['zh-CN', 'ms-MY', 'en-US'];
|
||||
const missing = [];
|
||||
|
||||
for (const { msgKey } of keys) {
|
||||
for (const locale of locales) {
|
||||
const exists = await this.prisma.i18nMessage.findUnique({
|
||||
where: { msgKey_locale: { msgKey, locale } },
|
||||
});
|
||||
if (!exists) missing.push({ msgKey, locale });
|
||||
}
|
||||
}
|
||||
return missing;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user