|
| 1 | +import { Inject, Injectable, Scope } from '@nestjs/common' |
| 2 | +import type * as Schema from '../assets/locales/en.json' |
| 3 | +import * as en from '../assets/locales/en.json' |
| 4 | +import * as pl from '../assets/locales/pl.json' |
| 5 | +import { REQUEST } from '@nestjs/core' |
| 6 | +import format from 'string-format' |
| 7 | + |
| 8 | +type PathsToStringProps<T> = T extends string |
| 9 | + ? [] |
| 10 | + : { |
| 11 | + [K in Extract<keyof T, string>]: [K, ...PathsToStringProps<T[K]>] |
| 12 | + }[Extract<keyof T, string>] |
| 13 | + |
| 14 | +type Join<T extends string[]> = T extends [] |
| 15 | + ? never |
| 16 | + : T extends [infer F] |
| 17 | + ? F |
| 18 | + : T extends [infer F, ...infer R] |
| 19 | + ? F extends string |
| 20 | + ? `${F}.${Join<Extract<R, string[]>>}` |
| 21 | + : never |
| 22 | + : string |
| 23 | + |
| 24 | +@Injectable({ scope: Scope.REQUEST, durable: true }) |
| 25 | +export class I18nService { |
| 26 | + constructor( |
| 27 | + @Inject(REQUEST) private readonly payload: { localeCode: string }, |
| 28 | + ) {} |
| 29 | + |
| 30 | + public static readonly defaultLanguage = 'en' |
| 31 | + public static readonly supportedLanguages = ['en', 'pl'] |
| 32 | + private readonly locales: Record<string, typeof Schema> = { en, pl } |
| 33 | + |
| 34 | + translate( |
| 35 | + key: Join<PathsToStringProps<typeof Schema>>, |
| 36 | + ...args: Array<string | Record<string, unknown>> |
| 37 | + ): string { |
| 38 | + const locale = |
| 39 | + this.locales[this.payload.localeCode ?? I18nService.defaultLanguage] |
| 40 | + |
| 41 | + // To support dot notation: "ERRORS.USER_NOT_FOUND" |
| 42 | + const text: string = key.split('.').reduce((o, i) => o[i], locale) |
| 43 | + return format(text, ...args) |
| 44 | + } |
| 45 | +} |
0 commit comments