Skip to content

Commit

Permalink
feat: update i18n services (#66)
Browse files Browse the repository at this point in the history
* feat: updated translator services

* test: fixed wrong import in test

* chore: add exports to index.ts

Co-authored-by: Wouter Termont <[email protected]>
  • Loading branch information
lem-onade and woutermont authored Oct 7, 2021
1 parent 45e46c2 commit ede4481
Show file tree
Hide file tree
Showing 11 changed files with 448 additions and 10 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { DGTErrorArgument, MemoryTranslator } from '@digita-ai/dgt-utils';
import { DGTErrorArgument } from '@digita-ai/dgt-utils';
import { MockTranslator } from '../../services/i18n/mock-translator';
import { Alert } from './alert';
import { AlertComponent } from './alert.component';

Expand Down Expand Up @@ -47,14 +48,14 @@ describe('AlertComponent', () => {
message: 'foo',
};

component.translator = new MemoryTranslator([ { key: 'foo', value:'bar', locale:'en-GB' } ], 'en-GB');
component.translator = new MockTranslator('en-GB');

window.document.body.appendChild(component);
await component.updateComplete;

const message = window.document.body.getElementsByTagName('nde-alert')[0].shadowRoot.querySelector('.message').innerHTML.replace(/<!---->/g, '');

expect(message).toBe('bar');
expect(message).toBe(component.alert.message);

});

Expand All @@ -65,7 +66,7 @@ describe('AlertComponent', () => {
message: 'foo',
};

component.translator = new MemoryTranslator([ { key: 'lorem', value:'bar', locale:'en-GB' } ], 'en-GB');
component.translator = new MockTranslator('en-GB');

window.document.body.appendChild(component);
await component.updateComplete;
Expand Down
3 changes: 3 additions & 0 deletions packages/dgt-components/lib/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,6 @@ export * from './models/source.model';
export * from './models/triple.model';
export * from './services/solid-sdk.service';
export * from './services/solid.service';
export * from './services/i18n/memory-translator';
export * from './services/i18n/mock-translator';
export * from './services/i18n/translator';
138 changes: 138 additions & 0 deletions packages/dgt-components/lib/services/i18n/memory-translator.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
import fetchMock from 'jest-fetch-mock';
import { MemoryTranslator } from './memory-translator';
import { TRANSLATIONS_LOADED } from './translator';

describe('MemoryTranslator', () => {

let service: MemoryTranslator;

const mockResponse = JSON.stringify({
'foo': {
'foo': 'Foo',
'bar': 'Bar',
},
});

beforeEach(async () => {

fetchMock.resetMocks();

fetchMock.mockResponse(mockResponse);

service = new MemoryTranslator('en-GB');

});

afterEach(() => {

fetchMock.resetMocks();

});

it('should be correctly instantiated', () => {

expect(service).toBeTruthy();

});

describe('translate', () => {

it('Should return an existing key in an existing locale.', () => {

const value = service.translate('foo.foo');

expect(value).toEqual('Foo');

});

it('Should translate by using the default locale when no locale was given.', () => {

const value = service.translate('foo.bar');

expect(value).toEqual('Bar');

});

it('Should return the input key with an non-existing key in an existing locale.', () => {

const value = service.translate('lorem');

expect(value).toEqual('[lorem]');

});

it('Should throw error when key is undefined.', () => {

expect(()=>service.translate('')).toThrow(Error);

});

});

describe('setLang', () => {

const newLang = 'en-US';

it('should not set new language when invalid JSON', async () => {

fetchMock.mockIf(/en-US/, '<not-json>');
fetchMock.mockIf(/en-GB/, mockResponse);

await service.setLang(newLang);
expect(service.lang).not.toEqual(newLang);

});

it('should not set new language when fetch throws error', async () => {

fetchMock.mockResponse(async (req) => {

if (req.url.includes('en-US')) {

throw new Error();

} else {

return mockResponse;

}

});

await service.setLang(newLang);
expect(service.lang).not.toEqual(newLang);

});

it('should set new language correctly', async () => {

await service.setLang('nl-BE');
expect(service.getLang()).toEqual('nl-BE');

});

it('should fire event when done', async (done) => {

service.addEventListener(TRANSLATIONS_LOADED, () => {

done();

});

await service.setLang('nl-BE');

});

});

describe('getLang', () => {

it('should return the current language', async () => {

expect(service.getLang()).toEqual(service.lang);

});

});

});
89 changes: 89 additions & 0 deletions packages/dgt-components/lib/services/i18n/memory-translator.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import { registerTranslateConfig, use, get, Values, ValuesCallback, ITranslateConfig, Strings } from '@appnest/lit-translate';
import { TranslationsLoadedEvent, Translator } from './translator';

/**
* An implementation of a Translator which stores translations in-memory.
*/
export class MemoryTranslator extends Translator {

/**
* Instantiates a MemoryTranslator.
*
* @param lang The default locale to use when translating.
*/
constructor(public lang: string) {

super();
this.setLang(lang);

}

/**
* Translates a key to a specific locale.
*
* @param key The key of the translation.
* @param locale The locale to which the message should be translated. Overrides the default locale.
* @returns The translated text.
*
* @throws {@link Error}
* This error is thrown when either no locale or key have been given.
*/

translate(key: string, values?: Values | ValuesCallback, config?: ITranslateConfig): string {

if (!key) {

throw new Error('Argument key should be set.');

}

return get(key, values, config);

}

/**
* Returns the language currently used by translator
*
* @returns The language currently used by translator
*/
getLang(): string {

return this.lang;

}

/**
* Updates the translator's language if a relevant translation file exists
* for this new language. Otherwise, falls back to the previously used language
*
* @param lang The new language to use
*/
async setLang(lang: string): Promise<void>{

this.loaded = false;

let translations: Promise<Strings>;

try {

translations = await (await fetch(`${window.location.origin}/${lang}.json`)).json();
this.lang = lang;

} catch(e) {

translations = await (await fetch(`${window.location.origin}/${this.lang}.json`)).json();

}

registerTranslateConfig({
loader: async () => translations,
});

await use(this.lang);

this.loaded = true;
this.dispatchEvent(new TranslationsLoadedEvent());

}

}
56 changes: 56 additions & 0 deletions packages/dgt-components/lib/services/i18n/mock-translator.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import { MockTranslator } from './mock-translator';

describe('MockTranslator', () => {

let service: MockTranslator;

beforeEach(async () => {

service = new MockTranslator('en-GB');

});

it('should create', () => {

service = new MockTranslator();
expect(service).toBeTruthy();
expect(service.lang).toEqual('nl-NL');

service = new MockTranslator('en-GB');
expect(service).toBeTruthy();
expect(service.lang).toEqual('en-GB');

});

describe('translate', () => {

it('should return key', () => {

expect(service.translate('test.key')).toEqual('test.key');

});

});

describe('getLang', () => {

it('should return lang', () => {

expect(service.getLang()).toEqual('en-GB');

});

});

describe('setLang', () => {

it('should set lang', async () => {

await service.setLang('nl-NL');
expect(service.lang).toEqual('nl-NL');

});

});

});
35 changes: 35 additions & 0 deletions packages/dgt-components/lib/services/i18n/mock-translator.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { TranslationsLoadedEvent, Translator } from './translator';

export class MockTranslator extends Translator {

public loaded = true;

constructor(public lang: string = 'nl-NL') {

super();
this.setLang(this.lang);

}

translate(key: string): string {

return key;

}

getLang(): string {

return this.lang;

}
setLang(lang: string): Promise<void> {

this.lang = lang;
this.loaded = true;
this.dispatchEvent(new TranslationsLoadedEvent());

return new Promise((r) => r());

}

}
Loading

0 comments on commit ede4481

Please sign in to comment.