Skip to content

Commit

Permalink
refactor: update i18next to v23
Browse files Browse the repository at this point in the history
typings: `getT` now returns `TFunction` with the correct default namespace
typings: `LocalePrefixKey`'s type now doesn't force a `commands/` prefix
typings: `LocalePrefixKey` now uses i18next's `nsSeparator` type instead of a hardcoded `:`
typings: All functions using `TypedT` now requires `LocalePrefixKey`

BREAKING CHANGE: refactor: Removed `resolveKey`, use `getSupportedLanguageT(interaction)(...args)` instead
BREAKING CHANGE: refactor: Removed `resolveUserKey`, use `getSupportedUserLanguageT(interaction)(...args)` instead
BREAKING CHANGE: typings: Removed `T` type utility function
BREAKING CHANGE: typings: Removed `FT` type utility function
BREAKING CHANGE: typings: Removed `TypedT` type utility
BREAKING CHANGE: typings: Removed `TypedFT` type utility
BREAKING CHANGE: typings: Removed `Value` type utility
BREAKING CHANGE: typings: Removed `Values` type utility
BREAKING CHANGE: typings: Removed `Difference` type utility
BREAKING CHANGE: typings: `i18next.TFunction` is not longer augmented, `lng` and `ns` is not longer assumed to exist
  • Loading branch information
kyranet committed Aug 20, 2023
1 parent e54a14a commit 2e39517
Show file tree
Hide file tree
Showing 6 changed files with 12 additions and 96 deletions.
2 changes: 2 additions & 0 deletions packages/http-framework-i18n/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ addFormatters(
await init();
```

> **Note**: If you want to customize the options, please check [i18next's TypeScript guide](https://www.i18next.com/overview/typescript) to improve the experience.
### Definition

```typescript
Expand Down
17 changes: 0 additions & 17 deletions packages/http-framework-i18n/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,3 @@
export { default as i18next, type InitOptions, type TFunction, type TOptions, type TOptionsBase } from 'i18next';
export * from './lib/functions.js';
export * from './lib/registry.js';
export type * from './lib/types.js';
export * from './lib/utils.js';

import type { NonNullObject } from '@sapphire/utilities';
import type { TypedFT, TypedT } from './lib/types.js';

declare module 'i18next' {
export interface TFunction {
lng: string;
ns?: string;

<TReturn>(key: TypedT<TReturn>, options?: TOptionsBase | string): TReturn;
<TReturn>(key: TypedT<TReturn>, defaultValue: TReturn, options?: TOptionsBase | string): TReturn;
<TArgs extends NonNullObject, TReturn>(key: TypedFT<TArgs, TReturn>, options?: TOptions<TArgs>): TReturn;
<TArgs extends NonNullObject, TReturn>(key: TypedFT<TArgs, TReturn>, defaultValue: TReturn, options?: TOptions<TArgs>): TReturn;
}
}
10 changes: 0 additions & 10 deletions packages/http-framework-i18n/src/lib/functions.ts

This file was deleted.

2 changes: 1 addition & 1 deletion packages/http-framework-i18n/src/lib/registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ async function loadLocale(directory: string, ns: string) {
}

const fixedCache = new Collection<LocaleString, TFunction>();
export function getT(locale: LocaleString): TFunction<'translation', undefined, 'translation'> {
export function getT(locale: LocaleString): TFunction {
if (!loadedLocales.has(locale)) throw new ReferenceError(`Invalid language (${locale})`);
return fixedCache.ensure(locale, () => getFixedT(locale));
}
21 changes: 0 additions & 21 deletions packages/http-framework-i18n/src/lib/types.ts

This file was deleted.

56 changes: 9 additions & 47 deletions packages/http-framework-i18n/src/lib/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@ import { Collection } from '@discordjs/collection';
import type { NonNullObject } from '@sapphire/utilities';
import { lazy } from '@sapphire/utilities';
import type { APIInteraction, APIPingInteraction, LocaleString, LocalizationMap } from 'discord-api-types/v10';
import type { TFunction, TOptions, TOptionsBase } from 'i18next';
import type { TFunction, TypeOptions } from 'i18next';
import { getT, loadedLocales } from './registry.js';
import type { LocalePrefixKey, TypedFT, TypedT } from './types.js';

export type Interaction = Pick<Exclude<APIInteraction, APIPingInteraction>, 'locale' | 'guild_locale' | 'guild_id'>;
export type LocaleSeparator = TypeOptions['nsSeparator'];
export type LocalePrefixKey = `${string}${LocaleSeparator}${string}`;

export function getSupportedUserLanguageName(interaction: Interaction): LocaleString {
if (loadedLocales.has(interaction.locale)) return interaction.locale;
Expand All @@ -31,45 +32,6 @@ export function getSupportedLanguageT(interaction: Interaction): TFunction {
return getT(getSupportedLanguageName(interaction));
}

export function resolveUserKey<TReturn>(interaction: Interaction, key: TypedT<TReturn>, options?: TOptionsBase | string): TReturn;
export function resolveUserKey<TReturn>(
interaction: Interaction,
key: TypedT<TReturn>,
defaultValue: TReturn,
options?: TOptionsBase | string
): TReturn;
export function resolveUserKey<TArgs extends NonNullObject, TReturn>(
interaction: Interaction,
key: TypedFT<TArgs, TReturn>,
options?: TOptions<TArgs>
): TReturn;
export function resolveUserKey<TArgs extends NonNullObject, TReturn>(
interaction: Interaction,
key: TypedFT<TArgs, TReturn>,
defaultValue: TReturn,
options?: TOptions<TArgs>
): TReturn;
export function resolveUserKey(interaction: Interaction, ...args: [any, any, any?]) {
return getSupportedUserLanguageT(interaction)(...args);
}

export function resolveKey<TReturn>(interaction: Interaction, key: TypedT<TReturn>, options?: TOptionsBase | string): TReturn;
export function resolveKey<TReturn>(interaction: Interaction, key: TypedT<TReturn>, defaultValue: TReturn, options?: TOptionsBase | string): TReturn;
export function resolveKey<TArgs extends NonNullObject, TReturn>(
interaction: Interaction,
key: TypedFT<TArgs, TReturn>,
options?: TOptions<TArgs>
): TReturn;
export function resolveKey<TArgs extends NonNullObject, TReturn>(
interaction: Interaction,
key: TypedFT<TArgs, TReturn>,
defaultValue: TReturn,
options?: TOptions<TArgs>
): TReturn;
export function resolveKey(interaction: Interaction, ...args: [any, any, any?]) {
return getSupportedLanguageT(interaction)(...args);
}

const getLocales = lazy(() => new Collection([...loadedLocales].map((locale) => [locale, getT(locale)])));
const getDefaultT = lazy(() => {
const defaultT = getLocales().get('en-US');
Expand All @@ -83,7 +45,7 @@ const getDefaultT = lazy(() => {
* @returns The retrieved data.
* @remarks This should be called **strictly** after loading the locales.
*/
export function getLocalizedData(key: TypedT): LocalizedData {
export function getLocalizedData(key: LocalePrefixKey): LocalizedData {
const locales = getLocales();
const defaultT = getDefaultT();

Expand All @@ -99,7 +61,7 @@ export function getLocalizedData(key: TypedT): LocalizedData {
* @param key The key to get the localizations from.
* @returns The updated builder.
*/
export function applyNameLocalizedBuilder<T extends BuilderWithName>(builder: T, key: TypedT) {
export function applyNameLocalizedBuilder<T extends BuilderWithName>(builder: T, key: LocalePrefixKey) {
const result = getLocalizedData(key);
return builder.setName(result.value).setNameLocalizations(result.localizations);
}
Expand All @@ -110,7 +72,7 @@ export function applyNameLocalizedBuilder<T extends BuilderWithName>(builder: T,
* @param key The key to get the localizations from.
* @returns The updated builder.
*/
export function applyDescriptionLocalizedBuilder<T extends BuilderWithDescription>(builder: T, key: TypedT) {
export function applyDescriptionLocalizedBuilder<T extends BuilderWithDescription>(builder: T, key: LocalePrefixKey) {
const result = getLocalizedData(key);
return builder.setDescription(result.value).setDescriptionLocalizations(result.localizations);
}
Expand All @@ -126,16 +88,16 @@ export function applyDescriptionLocalizedBuilder<T extends BuilderWithDescriptio
*/
export function applyLocalizedBuilder<T extends BuilderWithNameAndDescription>(
builder: T,
...params: [root: LocalePrefixKey] | [name: TypedT, description: TypedT]
...params: [root: LocalePrefixKey] | [name: LocalePrefixKey, description: LocalePrefixKey]
): T {
const [localeName, localeDescription] = params.length === 1 ? [`${params[0]}Name` as TypedT, `${params[0]}Description` as TypedT] : params;
const [localeName, localeDescription] = params.length === 1 ? [`${params[0]}Name` as const, `${params[0]}Description` as const] : params;

applyNameLocalizedBuilder(builder, localeName);
applyDescriptionLocalizedBuilder(builder, localeDescription);
return builder;
}

export function createSelectMenuChoiceName<V extends NonNullObject>(key: TypedT, value?: V): createSelectMenuChoiceName.Result<V> {
export function createSelectMenuChoiceName<V extends NonNullObject>(key: LocalePrefixKey, value?: V): createSelectMenuChoiceName.Result<V> {
const result = getLocalizedData(key);
return {
...value,
Expand Down

0 comments on commit 2e39517

Please sign in to comment.