feat(i18n): allow custom adapters

This commit is contained in:
teidesu 2022-08-29 18:53:27 +03:00
parent ea299cacca
commit 689533c549
3 changed files with 42 additions and 11 deletions

View file

@ -1,10 +1,15 @@
import { MtArgumentError, ParsedUpdate } from '@mtcute/client' import { MtArgumentError, ParsedUpdate } from '@mtcute/client'
import { I18nValue, MtcuteI18nFunction, OtherLanguageWrap } from './types' import {
I18nValue,
MtcuteI18nAdapter,
MtcuteI18nFunction,
OtherLanguageWrap,
} from './types'
import { createI18nStringsIndex, extractLanguageFromUpdate } from './utils' import { createI18nStringsIndex, extractLanguageFromUpdate } from './utils'
export * from './types' export * from './types'
export interface MtcuteI18nParameters<Strings> { export interface MtcuteI18nParameters<Strings, Input> {
/** /**
* Primary language which will also be used as a fallback * Primary language which will also be used as a fallback
*/ */
@ -28,15 +33,21 @@ export interface MtcuteI18nParameters<Strings> {
* Defaults to {@link primaryLanguage} * Defaults to {@link primaryLanguage}
*/ */
defaultLanguage?: string defaultLanguage?: string
/**
* Adapter that will be used to extract language from the update.
*/
adapter?: MtcuteI18nAdapter<Input>
} }
export function createMtcuteI18n<Strings>( export function createMtcuteI18n<Strings, Input>(
params: MtcuteI18nParameters<Strings> params: MtcuteI18nParameters<Strings, Input>
): MtcuteI18nFunction<Strings> { ): MtcuteI18nFunction<Strings, Input> {
const { const {
primaryLanguage, primaryLanguage,
otherLanguages, otherLanguages,
defaultLanguage = primaryLanguage.name, defaultLanguage = primaryLanguage.name,
adapter = extractLanguageFromUpdate as any as MtcuteI18nAdapter<Input>,
} = params } = params
const indexes: Record<string, Record<string, I18nValue>> = {} const indexes: Record<string, Record<string, I18nValue>> = {}
@ -54,11 +65,15 @@ export function createMtcuteI18n<Strings>(
) )
} }
const tr = (lang: ParsedUpdate['data'] | string | null, key: string, ...params: any[]) => { const tr = (
lang: Input | string | null,
key: string,
...params: any[]
) => {
if (lang === null) lang = defaultLanguage if (lang === null) lang = defaultLanguage
if (typeof lang === 'object') { if (typeof lang !== 'string') {
lang = extractLanguageFromUpdate(lang) ?? defaultLanguage lang = adapter(lang) ?? defaultLanguage
} }
const strings = indexes[lang] ?? fallbackIndex const strings = indexes[lang] ?? fallbackIndex
@ -72,5 +87,5 @@ export function createMtcuteI18n<Strings>(
return val return val
} }
return tr as MtcuteI18nFunction<Strings> return tr as MtcuteI18nFunction<Strings, Input>
} }

View file

@ -25,10 +25,12 @@ type ExtractParameter<Strings, K extends string> = GetValueNested<
? R ? R
: never : never
export type MtcuteI18nFunction<Strings> = < export type MtcuteI18nAdapter<Input> = (obj: Input) => string | null | undefined
export type MtcuteI18nFunction<Strings, Input = ParsedUpdate['data']> = <
K extends NestedKeysDelimited<Strings> K extends NestedKeysDelimited<Strings>
>( >(
lang: ParsedUpdate['data'] | string | null, lang: Input | string | null,
key: K, key: K,
...params: ExtractParameter<Strings, K> ...params: ExtractParameter<Strings, K>
) => string | FormattedString<any> ) => string | FormattedString<any>

View file

@ -91,4 +91,18 @@ describe('i18n', () => {
expect(tr(message, 'direct')).to.equal('Привет') expect(tr(message, 'direct')).to.equal('Привет')
}) })
it('should accept custom adapters', () => {
const tr = createMtcuteI18n({
primaryLanguage: {
name: 'en',
strings: en,
},
otherLanguages: { ru },
adapter: (num: number) => num === 1 ? 'en' : 'ru',
})
expect(tr(1, 'direct')).to.equal('Hello')
expect(tr(2, 'direct')).to.equal('Привет')
})
}) })