From 6584c1375b231985251b81cb8b64dc2d214103f2 Mon Sep 17 00:00:00 2001 From: Christian Kaisermann Date: Thu, 26 Jul 2018 01:40:19 -0300 Subject: [PATCH] Add svelte, sveltify the code and add some tests --- package-lock.json | 6 +++++ package.json | 1 + src/interfaces.ts | 17 +++++++++++++ src/svelte-i18n.ts | 29 +++++++++++----------- src/utils.ts | 18 ++++++++++++++ test/svelte-i18n.test.ts | 53 ++++++++++++++++++++++++++++++++++------ 6 files changed, 102 insertions(+), 22 deletions(-) create mode 100644 src/utils.ts diff --git a/package-lock.json b/package-lock.json index 846b74e..5109831 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9782,6 +9782,12 @@ "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", "dev": true }, + "svelte": { + "version": "2.9.7", + "resolved": "https://registry.npmjs.org/svelte/-/svelte-2.9.7.tgz", + "integrity": "sha512-+OwyqaGgy25vKBmZOR7usUE4bK1sHnxvv+Q+8IXFZsanvR+acTjIL+GRdRS8XRvoaxfxM47DpwWk1wo4RV0ucg==", + "dev": true + }, "symbol-observable": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz", diff --git a/package.json b/package.json index 692e510..1ff78af 100644 --- a/package.json +++ b/package.json @@ -99,6 +99,7 @@ "rollup-plugin-sourcemaps": "^0.4.2", "rollup-plugin-typescript2": "^0.11.1", "semantic-release": "^15.0.0", + "svelte": "^2.9.7", "ts-jest": "^22.0.0", "ts-node": "^6.0.0", "tslint": "^5.8.0", diff --git a/src/interfaces.ts b/src/interfaces.ts index 7ac40ab..c4edf03 100644 --- a/src/interfaces.ts +++ b/src/interfaces.ts @@ -11,3 +11,20 @@ export interface Sveltei18n { upper: TranslationGetter lower: TranslationGetter } +export interface SvelteEventListener { + cancel(): void +} + +export interface SvelteStore { + on: (event: string, callback: Function) => SvelteEventListener + set: (newState: Object) => void + fire: (event: string, value: any) => void + [prop: string]: any +} + +export interface Locale { + [id: string | number]: string +} +export interface Locales { + [locale: string]: Locale +} diff --git a/src/svelte-i18n.ts b/src/svelte-i18n.ts index 909df4e..1ddfa52 100644 --- a/src/svelte-i18n.ts +++ b/src/svelte-i18n.ts @@ -1,18 +1,19 @@ -import { InterpolationObj, Sveltei18n } from './interfaces' +import { InterpolationObj, Sveltei18n, SvelteStore, Locale, Locales } from './interfaces' +import { capitalize, titlelize, upper, lower, getNestedProp } from './utils' -export default function() { - const _ = function(str: string, values: InterpolationObj) { - return str - } +export default function(store: SvelteStore, locales: Locales) { + store.locale = (locale: string) => store.fire('locale', locale) + store.on('locale', function(locale: string) { + const localeDict: Locale = locales[locale] + const _ = function(id, values) { + return getNestedProp(localeDict, id) || id + } - Object.assign(_, { - capitalize: (id: string, values: InterpolationObj) => - _(id, values).replace(/(^|\s)\S/, l => l.toUpperCase()), - titlelize: (id: string, values: InterpolationObj) => - _(id, values).replace(/(^|\s)\S/g, l => l.toUpperCase()), - upper: (id: string, values: InterpolationObj) => _(id, values).toLocaleUpperCase(), - lower: (id: string, values: InterpolationObj) => _(id, values).toLocaleLowerCase() + _.capitalize = (id, values) => capitalize(_(id, values)) + _.titlelize = (id, values) => titlelize(_(id, values)) + _.upper = (id, values) => upper(_(id, values)) + _.lower = (id, values) => lower(_(id, values)) + + store.set({ locale, _ }) }) - - return _ } diff --git a/src/utils.ts b/src/utils.ts new file mode 100644 index 0000000..c316052 --- /dev/null +++ b/src/utils.ts @@ -0,0 +1,18 @@ +export const capitalize = (str: string) => str.replace(/(^|\s)\S/, l => l.toUpperCase()) +export const titlelize = (str: string) => str.replace(/(^|\s)\S/g, l => l.toUpperCase()) +export const upper = (str: string) => str.toLocaleUpperCase() +export const lower = (str: string) => str.toLocaleLowerCase() + +export const getNestedProp = (obj: { [prop: string]: any }, path: string) => { + try { + return path + .replace('[', '.') + .replace(']', '') + .split('.') + .reduce(function(o, property) { + return o[property] + }, obj) + } catch (err) { + return undefined + } +} diff --git a/test/svelte-i18n.test.ts b/test/svelte-i18n.test.ts index 42aefb0..4b69218 100644 --- a/test/svelte-i18n.test.ts +++ b/test/svelte-i18n.test.ts @@ -1,14 +1,51 @@ -import DummyClass from '../src/svelte-i18n' +import i18n from '../src/svelte-i18n' +import { Store } from 'svelte/store.umd' +import { capitalize, titlelize, upper, lower, getNestedProp } from '../src/utils' + +const store = new Store() +const locales = { + 'pt-br': { + test: 'teste', + phrase: 'Adoro banana', + phrases: ['Frase 1', 'Frase 2'] + }, + po: { + test: 'prøve', + phrase: 'Jeg elsker banan', + phrases: ['sætning 1', 'sætning 2'] + } +} + +i18n(store, locales) /** * Dummy test */ -describe('Dummy test', () => { - it('works if true is truthy', () => { - expect(true).toBeTruthy() - }) - - it('DummyClass is instantiable', () => { - expect(new DummyClass()).toBeInstanceOf(DummyClass) +describe('utils', () => { + it('works', () => { + expect(getNestedProp(store['pt-br'], 'phrases[3]')).toBe(undefined) + }) +}) +describe('Dummy test', () => { + it('works if true is truthy', () => { + expect(store.get().locale).toBeFalsy() + expect(store.get()._).toBeFalsy() + + store.fire('locale', 'en') + expect(store.get().locale).toBe('en') + store.locale('pt-br') + expect(store.get().locale).toBe('pt-br') + expect(store.get()._).toBeInstanceOf(Function) + expect(store.get()._('non-existent')).toBe('non-existent') + expect(store.get()._('test')).toBe(locales['pt-br'].test) + store.fire('locale', 'po') + expect(store.get()._('test')).not.toBe(locales['pt-br'].test) + expect(store.get()._('test')).toBe(locales.po.test) + expect(store.get()._('phrases[1]')).toBe(locales.po.phrases[1]) + expect(store.get()._('phrases[2]')).toBe('phrases[2]') + expect(store.get()._.capitalize('phrase')).toBe(capitalize(locales.po.phrase)) + expect(store.get()._.titlelize('phrase')).toBe(titlelize(locales.po.phrase)) + expect(store.get()._.upper('phrase')).toBe(upper(locales.po.phrase)) + expect(store.get()._.lower('phrase')).toBe(lower(locales.po.phrase)) }) })