Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(i18next): add hot-module-replacement to reload i18next resources #224

Merged
merged 5 commits into from
Jan 12, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/i18next/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
"dependencies": {
"@sapphire/utilities": "^3.1.0",
"@types/i18next-fs-backend": "^1.1.2",
"chokidar": "^3.5.2",
"i18next": "^21.6.5",
"i18next-fs-backend": "^1.1.4",
"tslib": "^2.3.1"
Expand Down
20 changes: 20 additions & 0 deletions packages/i18next/src/lib/InternationalizationHandler.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { fromAsync, isErr } from '@sapphire/framework';
import { container, getRootData } from '@sapphire/pieces';
import { Awaitable, isFunction, NonNullObject } from '@sapphire/utilities';
import { opendir } from 'fs/promises';
Expand Down Expand Up @@ -214,4 +215,23 @@ export class InternationalizationHandler {

return { namespaces: [...new Set(namespaces)], languages };
}

public async reloadResources() {
const result = await fromAsync(async () => {
let languages = this.options.hmr?.languages;
let namespaces = this.options.hmr?.namespaces;
if (!languages || !namespaces) {
const languageDirectoryResult = await this.walkLanguageDirectory(this.languagesDirectory);
languages ??= languageDirectoryResult.languages;
namespaces ??= languageDirectoryResult.namespaces;
}

await i18next.reloadResources(languages, namespaces);
container.logger.info('[i18next-Plugin] Reloaded language resources.');
});

if (isErr(result)) {
container.logger.error('[i18next-Plugin]: Failed to reload language resources.', result.error);
}
}
}
37 changes: 37 additions & 0 deletions packages/i18next/src/lib/types.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,38 @@
import type { Awaitable, NonNullObject } from '@sapphire/utilities';
import type { WatchOptions } from 'chokidar';
import type { Guild, Message, MessageOptions, StageChannel, StoreChannel, User, VoiceChannel } from 'discord.js';
import type { InitOptions, StringMap, TFunctionKeys, TOptions } from 'i18next';
import type { i18nextFsBackend } from 'i18next-fs-backend';

/**
* Configure whether to use Hot-Module-Replacement (HMR) for your i18next resources using these options. The minimum config to enable HMR is to set `enabled` to true. Any other properties are optional.
* @since 2.2.0
*/
export interface HMROptions {
/**
* HMR status for the i18next plugin.
sawa-ko marked this conversation as resolved.
Show resolved Hide resolved
* @default false
*/
enabled: boolean;

/**
* Languages that will be reloaded when updating the languages directory.
sawa-ko marked this conversation as resolved.
Show resolved Hide resolved
* @default All languages that are automatically resolved from your folder setup
*/
languages?: string | string[];

/**
* Namespaces that will be reloaded when updating the languages directory.
sawa-ko marked this conversation as resolved.
Show resolved Hide resolved
* @default All namespaces that are automatically resolved from your languages folder setup
*/
namespaces?: string | string[];

/**
* HMR options
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* HMR options
* Additional options to configure chokidar with

*/
options?: WatchOptions;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
options?: WatchOptions;
chokidarWatchOptions?: WatchOptions;

}

/**
* Used to dynamically add options based on found languages in {@link InternationalizationHandler#init}.
* @since 1.1.0
Expand Down Expand Up @@ -63,6 +93,13 @@ export interface InternationalizationOptions {
*/
formatters?: I18nextFormatters[];

/**
* Reload languages and namespaces when updating the languages directory.
*
* @since 2.2.0
*/
hmr?: HMROptions;

/**
* A function that is to be used to retrieve the language for the current context.
* Context exists of a {@link Guild `guild`}, a {@link DiscordChannel `channel`} and a {@link User `user`}.
Expand Down
13 changes: 12 additions & 1 deletion packages/i18next/src/register.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { container, Plugin, preGenericsInitialization, preLogin, SapphireClient } from '@sapphire/framework';
import { container, Plugin, preGenericsInitialization, preLogin, postLogin, SapphireClient } from '@sapphire/framework';
import { watch } from 'chokidar';
import type { ClientOptions } from 'discord.js';

import { InternationalizationClientOptions, InternationalizationHandler } from './index';

export class I18nextPlugin extends Plugin {
Expand All @@ -10,6 +12,15 @@ export class I18nextPlugin extends Plugin {
public static async [preLogin](this: SapphireClient): Promise<void> {
await container.i18n.init();
}

public static [postLogin](this: SapphireClient): void {
if (this.options.i18n?.hmr?.enabled) {
container.logger.info('[i18next-Plugin]: HMR enabled. Watching for languages changes.');
const hmr = watch(container.i18n.languagesDirectory, this.options.i18n.hmr.options);

for (const event of ['add', 'change', 'unlink']) hmr.on(event, () => container.i18n.reloadResources());
}
}
}

SapphireClient.plugins.registerPostInitializationHook(I18nextPlugin[preGenericsInitialization], 'I18next-PreGenericsInitialization');
Expand Down
1 change: 1 addition & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2071,6 +2071,7 @@ __metadata:
dependencies:
"@sapphire/utilities": ^3.1.0
"@types/i18next-fs-backend": ^1.1.2
chokidar: ^3.5.2
i18next: ^21.6.5
i18next-fs-backend: ^1.1.4
tslib: ^2.3.1
Expand Down