diff --git a/src/index.ts b/src/index.ts index 0349cbc..3419d64 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1 +1,59 @@ -export const myPackage = (taco = ''): string => `${taco} from my package`; +import { + getInterpolationFunctionKeys, + getFunctionParams, + getTranslationKeys, + t18Options, + Translations, + UnionOmit, + ValidValues, +} from './typings'; + +export class t18 { + private translations: Translations; + constructor(options: t18Options) { + this.translations = options.translations; + } + + t>( + key: Key, + args: getFunctionParams + ): string; + t( + key: UnionOmit, getInterpolationFunctionKeys> + ): string; + t(key: any, args?: any): string { + if (typeof key !== 'string') { + return 'INVALID KEY'; + } + + const objects = key.split('.'); + + let currentValue: ValidValues | Translations = this.translations; + for (const object of objects) { + if (typeof currentValue !== 'object') { + return 'INVALID PATH'; + } + + currentValue = currentValue[object]; + } + + const translation = currentValue; + + if (typeof currentValue === 'function') { + if (!args || !Array.isArray(args)) { + return 'INVALID INTERPOLATION FUNCTION ARGUMENTS'; + } + + const withInterpolationTranslation = currentValue(...args); + if (typeof withInterpolationTranslation !== 'string') { + return 'INVALID VALUE'; + } + } + + if (typeof currentValue === 'object') { + return 'INVALID PATH'; + } + + return currentValue; + } +} diff --git a/src/typings.d.ts b/src/typings.d.ts new file mode 100644 index 0000000..00ddd9e --- /dev/null +++ b/src/typings.d.ts @@ -0,0 +1,67 @@ +/*export interface LanguageFile { + language: string; + translations: T; +}*/ + +export interface t18Options { + translations: T; +} + +export interface Translations { + [key: string]: translations | ValidValues; +} + +type InterpolationFunction = (...args: any[]) => string; + +export type ValidValues = string | InterpolationFunction; //| ; + +export type getTranslationKeys = Id< + RecKeysOf +>; + +export type getFunctionParams< + Translation extends Translation, + Key extends getTranslationKeys +> = Id>; + +type Id = T extends T ? { [P in keyof T]: T[P] } : never; + +type RecKeysOf = { + [P in keyof Dir & (string | number)]: Dir[P] extends FileType + ? `${Prefix}${P}` + : RecKeysOf; +}[keyof Dir & (string | number)]; + +type UnionOmit = Target extends Props ? never : Target; + +export type getInterpolationFunctionKeys = UnionOmit< + getTranslationKeys, + Id> +>; + +export type getNotInterpolationFunctionKeys = UnionOmit< + getTranslationKeys, + getInterpolationFunctionKeys +>; + +type getParameters = T extends (...args: infer P) => any ? P : never; + +type RecParamsOf< + Dir, + FileType, + Prefix extends string = '', + Key extends string +> = { + [P in keyof Dir & (string | number)]: Dir[P] extends FileType + ? `${Prefix}${P}` extends Key + ? getParameters + : never + : RecParamsOf; +}[keyof Dir & (string | number)]; + +// for getFixedT :) +type RecAllPathsOf = { + [P in keyof Dir & (string | number)]: Dir[P] extends FileType + ? `${Prefix}${P}` + : RecAllPathsOf | `${Prefix}${P}`; +}[keyof Dir & (string | number)]; diff --git a/test/index.spec.ts b/test/index.spec.ts index d305240..a3e1966 100644 --- a/test/index.spec.ts +++ b/test/index.spec.ts @@ -1,13 +1,34 @@ -import { myPackage } from '../src'; +import { t18 } from '../src'; describe('index', () => { - describe('myPackage', () => { - it('should return a string containing the message', () => { - const message = 'Hello'; + describe('t18', () => { + it('should translate key to message', () => { + const message = 'Hello World!'; - const result = myPackage(message); + const translations = new t18({ + translations: { + general: { + hello_word: 'Hello World!', + }, + }, + }); - expect(result).toMatch(message); + expect(translations.t('general.hello_word')).toMatch(message); + }); + + it('should return welcome message with name', () => { + const message = (name: string) => `Welcome ${name}!`; + const name = 'Bob'; + + const translations = new t18({ + translations: { + messages: { + welcome: message, + }, + }, + }); + + expect(translations.t('messages.welcome', [name])).toMatch(message(name)); }); }); });