Skip to content

Commit

Permalink
feat(locale): get current language from config (fixes #84)
Browse files Browse the repository at this point in the history
  • Loading branch information
ssube committed May 29, 2021
1 parent 28c239b commit d8e18ef
Show file tree
Hide file tree
Showing 11 changed files with 80 additions and 45 deletions.
1 change: 1 addition & 0 deletions data/config.yml
Expand Up @@ -26,3 +26,4 @@ locale:
load: load
quit: quit
save: save
current: en
1 change: 1 addition & 0 deletions src/index.html
Expand Up @@ -23,6 +23,7 @@
load: load
quit: quit
save: save
current: en
</script>
<div id="app"></div>
<script src="./bundle/browser.js">
Expand Down
5 changes: 4 additions & 1 deletion src/main.ts
Expand Up @@ -3,7 +3,7 @@ import { BaseOptions, Container, Module } from 'noicejs';

import { BunyanLogger } from './logger/BunyanLogger';
import { ActorType } from './model/entity/Actor';
import { INJECT_ACTOR, INJECT_LOADER, INJECT_LOCALE, INJECT_PARSER, INJECT_RENDER, INJECT_STATE } from './module';
import { INJECT_ACTOR, INJECT_CONFIG, INJECT_LOADER, INJECT_LOCALE, INJECT_PARSER, INJECT_RENDER, INJECT_STATE } from './module';
import { ActorLocator, ActorModule } from './module/ActorModule';
import { BrowserModule } from './module/BrowserModule';
import { LocalModule } from './module/LocalModule';
Expand Down Expand Up @@ -45,6 +45,9 @@ export async function main(args: Array<string>): Promise<number> {
return new ctor();
});

// TODO: bind to base module, once such a thing exists
modules[0].bind(INJECT_CONFIG).toInstance(config);

// configure DI container
const container = Container.from(...modules);
await container.configure({
Expand Down
16 changes: 14 additions & 2 deletions src/model/file/Config.ts
Expand Up @@ -17,7 +17,9 @@ export interface ConfigLogger {

export interface ConfigFile {
logger: ConfigLogger;
locale: LocaleBundle;
locale: LocaleBundle & {
current: string;
};
}

export const CONFIG_SCHEMA: JSONSchemaType<ConfigFile> = {
Expand Down Expand Up @@ -61,7 +63,17 @@ export const CONFIG_SCHEMA: JSONSchemaType<ConfigFile> = {
],
additionalProperties: true,
},
locale: LOCALE_SCHEMA,
locale: {
type: 'object',
properties: {
...LOCALE_SCHEMA.properties,
current: {
type: 'string',
default: 'en',
},
},
required: ['bundles'],
},
},
required: [
'locale',
Expand Down
1 change: 1 addition & 0 deletions src/module/index.ts
@@ -1,4 +1,5 @@
// service symbols
export const INJECT_CONFIG = Symbol('inject-config');
export const INJECT_COUNTER = Symbol('inject-counter');
export const INJECT_EVENT = Symbol('inject-event-bus');
export const INJECT_LOADER = Symbol('inject-loader');
Expand Down
10 changes: 7 additions & 3 deletions src/service/locale/NextLocale.ts
Expand Up @@ -3,24 +3,28 @@ import i18next, { i18n } from 'i18next';
import { BaseOptions, Inject, Logger } from 'noicejs';

import { LocaleContext, LocaleService } from '.';
import { ConfigFile } from '../../model/file/Config';
import { LocaleBundle } from '../../model/file/Locale';
import { INJECT_EVENT, INJECT_LOGGER } from '../../module';
import { INJECT_CONFIG, INJECT_EVENT, INJECT_LOGGER } from '../../module';
import { EventBus } from '../event';

interface NextLocaleOptions extends BaseOptions {
[INJECT_CONFIG]?: ConfigFile;
[INJECT_EVENT]?: EventBus;
[INJECT_LOGGER]?: Logger;
}

@Inject(INJECT_EVENT, INJECT_LOGGER)
@Inject(INJECT_CONFIG, INJECT_EVENT, INJECT_LOGGER)
export class NextLocaleService implements LocaleService {
protected config: ConfigFile['locale'];
protected event: EventBus;
protected logger: Logger;

protected i18next?: i18n;
protected bundleLangs: Map<string, Set<string>>;

constructor(options: NextLocaleOptions) {
this.config = mustExist(options[INJECT_CONFIG]).locale;
this.event = mustExist(options[INJECT_EVENT]);
this.logger = mustExist(options[INJECT_LOGGER]).child({
kind: constructorName(this),
Expand All @@ -33,7 +37,7 @@ export class NextLocaleService implements LocaleService {
const inst = i18next.createInstance({
defaultNS: 'world',
fallbackNS: ['common'],
lng: 'en',
lng: this.config.current,
});
await inst.init();

Expand Down
38 changes: 38 additions & 0 deletions test/helper.ts
@@ -0,0 +1,38 @@
import { Container, LogLevel, Module, NullLogger } from 'noicejs';

import { ConfigFile } from '../src/model/file/Config';
import { INJECT_CONFIG, INJECT_LOGGER } from '../src/module';

export function getTestLogger() {
// TODO: return console/bunyan logger if TEST_LOGGER=that
return NullLogger.global;
}

export function getTestConfig(): ConfigFile {
return {
logger: {
level: LogLevel.DEBUG,
name: 'test',
streams: [],
},
locale: {
bundles: {},
current: 'en',
},
};
}

export async function getTestContainer(...modules: Array<Module>): Promise<Container> {
const config = getTestConfig();
const logger = getTestLogger();

modules[0].bind(INJECT_CONFIG).toInstance(config);
modules[0].bind(INJECT_LOGGER).toInstance(logger);

const container = Container.from(...modules);
await container.configure({
logger,
});

return container;
}
6 changes: 2 additions & 4 deletions test/module/TestActorModule.ts
Expand Up @@ -7,13 +7,11 @@ import { ActorLocator, ActorModule } from '../../src/module/ActorModule';
import { LocalModule } from '../../src/module/LocalModule';
import { PlayerActorService } from '../../src/service/actor/PlayerActor';
import { NextLocaleService } from '../../src/service/locale/NextLocale';
import { getTestContainer } from '../helper';

describe('actor module', () => {
it('should provide a player actor service for player actors', async () => {
const container = Container.from(new LocalModule(), new ActorModule());
await container.configure({
logger: NullLogger.global,
});
const container = await getTestContainer(new LocalModule(), new ActorModule());

const locale = await container.create<NextLocaleService, BaseOptions>(INJECT_LOCALE);
await locale.start();
Expand Down
13 changes: 5 additions & 8 deletions test/service/actor/TestPlayerActor.ts
@@ -1,5 +1,5 @@
import { expect } from 'chai';
import { BaseOptions, Container, NullLogger } from 'noicejs';
import { BaseOptions } from 'noicejs';

import { ActorType } from '../../../src/model/entity/Actor';
import { INJECT_ACTOR, INJECT_EVENT, INJECT_LOCALE } from '../../../src/module';
Expand All @@ -8,15 +8,11 @@ import { LocalModule } from '../../../src/module/LocalModule';
import { CommandEvent, EventBus } from '../../../src/service/event';
import { LocaleService } from '../../../src/service/locale';
import { onceWithRemove } from '../../../src/util/event';
import { getTestContainer } from '../../helper';

describe('player actor', () => {
it('should ', async () => {
const container = Container.from(new LocalModule(), new ActorModule());
await container.configure({
logger: NullLogger.global,
});

const event = await container.create<EventBus, BaseOptions>(INJECT_EVENT);
it('should parse render output into commands', async () => {
const container = await getTestContainer(new LocalModule(), new ActorModule());

const locale = await container.create<LocaleService, BaseOptions>(INJECT_LOCALE);
await locale.start();
Expand All @@ -31,6 +27,7 @@ describe('player actor', () => {
const index = 13;
const line = `foo bar ${index}`;

const event = await container.create<EventBus, BaseOptions>(INJECT_EVENT);
const { pending } = onceWithRemove<CommandEvent>(event, 'actor-command');

event.emit('render-output', {
Expand Down
20 changes: 4 additions & 16 deletions test/service/locale/TestNextLocale.ts
@@ -1,17 +1,13 @@
import { NotFoundError } from '@apextoaster/js-utils';
import { expect } from 'chai';
import { Container, NullLogger } from 'noicejs';

import { LocalModule } from '../../../src/module/LocalModule';
import { NextLocaleService } from '../../../src/service/locale/NextLocale';
import { getTestContainer } from '../../helper';

describe('next locale service', () => {
it('should have an i18next instance after being started', async () => {
const container = Container.from(new LocalModule());
await container.configure({
logger: NullLogger.global,
});

const container = await getTestContainer(new LocalModule());
const locale = await container.create(NextLocaleService);

expect(() => locale.getInstance()).to.throw(NotFoundError);
Expand All @@ -22,11 +18,7 @@ describe('next locale service', () => {
});

it('should prefer the world bundle', async () => {
const container = Container.from(new LocalModule());
await container.configure({
logger: NullLogger.global,
});

const container = await getTestContainer(new LocalModule());
const locale = await container.create(NextLocaleService);
await locale.start();

Expand All @@ -49,11 +41,7 @@ describe('next locale service', () => {
});

it('should translate keys with context', async () => {
const container = Container.from(new LocalModule());
await container.configure({
logger: NullLogger.global,
});

const container = await getTestContainer(new LocalModule());
const locale = await container.create(NextLocaleService);
await locale.start();

Expand Down
14 changes: 3 additions & 11 deletions test/service/tokenizer/TestWordTokenizer.ts
@@ -1,16 +1,12 @@
import { expect } from 'chai';
import { Container, NullLogger } from 'noicejs';

import { LocalModule } from '../../../src/module/LocalModule';
import { WordTokenizer } from '../../../src/service/tokenizer/WordTokenizer';
import { getTestContainer } from '../../helper';

describe('word tokenizer', () => {
it('should parse token lines', async () => {
const container = Container.from(new LocalModule());
await container.configure({
logger: NullLogger.global,
});

const container = await getTestContainer(new LocalModule());
const token = await container.create(WordTokenizer);

return expect(token.parse('foo')).to.eventually.deep.equal([{
Expand All @@ -22,11 +18,7 @@ describe('word tokenizer', () => {
});

it('should parse a final numeric segment as the command index', async () => {
const container = Container.from(new LocalModule());
await container.configure({
logger: NullLogger.global,
});

const container = await getTestContainer(new LocalModule());
const token = await container.create(WordTokenizer);

const index = 13;
Expand Down

0 comments on commit d8e18ef

Please sign in to comment.