Skip to content

Commit

Permalink
feat(src/index.ts): created main module
Browse files Browse the repository at this point in the history
  • Loading branch information
mortynex committed Oct 9, 2021
1 parent eaf314a commit bb89abe
Show file tree
Hide file tree
Showing 3 changed files with 153 additions and 7 deletions.
60 changes: 59 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
@@ -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<T extends Translations> {
private translations: Translations;
constructor(options: t18Options<T>) {
this.translations = options.translations;
}

t<Key extends getInterpolationFunctionKeys<T>>(
key: Key,
args: getFunctionParams<T, Key>
): string;
t(
key: UnionOmit<getTranslationKeys<T>, getInterpolationFunctionKeys<T>>
): 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;
}
}
67 changes: 67 additions & 0 deletions src/typings.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/*export interface LanguageFile<T> {
language: string;
translations: T;
}*/

export interface t18Options<T> {
translations: T;
}

export interface Translations {
[key: string]: translations | ValidValues;
}

type InterpolationFunction = (...args: any[]) => string;

export type ValidValues = string | InterpolationFunction; //| ;

export type getTranslationKeys<Translation extends Translation> = Id<
RecKeysOf<Translation, ValidValues, ''>
>;

export type getFunctionParams<
Translation extends Translation,
Key extends getTranslationKeys<Translation>
> = Id<RecParamsOf<Translation, ValidValues, '', Key>>;

type Id<T> = T extends T ? { [P in keyof T]: T[P] } : never;

type RecKeysOf<Dir, FileType, Prefix extends string> = {
[P in keyof Dir & (string | number)]: Dir[P] extends FileType
? `${Prefix}${P}`
: RecKeysOf<Dir[P], FileType, `${Prefix}${P}.`>;
}[keyof Dir & (string | number)];

type UnionOmit<Target, Props> = Target extends Props ? never : Target;

export type getInterpolationFunctionKeys<T extends Translations> = UnionOmit<
getTranslationKeys<T>,
Id<RecKeysOf<T, string, ''>>
>;

export type getNotInterpolationFunctionKeys<T extends Translations> = UnionOmit<
getTranslationKeys<T>,
getInterpolationFunctionKeys<T>
>;

type getParameters<T> = 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<Dir[P]>
: never
: RecParamsOf<Dir[P], FileType, `${Prefix}${P}.`, Key>;
}[keyof Dir & (string | number)];

// for getFixedT :)
type RecAllPathsOf<Dir, FileType, Prefix extends string> = {
[P in keyof Dir & (string | number)]: Dir[P] extends FileType
? `${Prefix}${P}`
: RecAllPathsOf<Dir[P], FileType, `${Prefix}${P}.`> | `${Prefix}${P}`;
}[keyof Dir & (string | number)];
33 changes: 27 additions & 6 deletions test/index.spec.ts
Original file line number Diff line number Diff line change
@@ -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));
});
});
});

0 comments on commit bb89abe

Please sign in to comment.