i18next plugin without namespaces

Hello, how would I get rid of the namespaces, and have it like this? I get invalid language provided now.
i18n: {
i18next: {
returnObjects: true,
},
defaultLanguageDirectory: '/var/tictactoe/languages',
backend: {
paths: ['{{lng}}.json'],
},
fetchLanguage: async (context: InternationalizationContext) => {
const locale = context.interactionGuildLocale || context.interactionLocale;
if (locale && container.i18n.languages.has(locale)) return locale;

return 'en-US';
},
},
i18n: {
i18next: {
returnObjects: true,
},
defaultLanguageDirectory: '/var/tictactoe/languages',
backend: {
paths: ['{{lng}}.json'],
},
fetchLanguage: async (context: InternationalizationContext) => {
const locale = context.interactionGuildLocale || context.interactionLocale;
if (locale && container.i18n.languages.has(locale)) return locale;

return 'en-US';
},
},
Maybe a file called index.json and then default to that ns if possible?
13 Replies
Favna
Favna2y ago
Make a folder called en-US then set defaultNamespace through options.
S222em
S222em2y ago
Okay yeah thanks
Favna
Favna2y ago
https://www.i18next.com/overview/api#setdefaultnamespace It should also be part of the client options where you are with the code above but searching the site only gives me this.
S222em
S222em2y ago
So how would I use the t function with defaultNS? Should it be like t(':key')? Im getting a not found on t('key')
Favna
Favna2y ago
Whats your config like rn
S222em
S222em2y ago
Nevermind t(':key') does not work either
i18n: {
i18next: {
returnObjects: true,
},
defaultLanguageDirectory: '/var/tictactoe/languages',
defaultNS: 'index',
fetchLanguage: async (context: InternationalizationContext) => {
const locale = context.interactionGuildLocale || context.interactionLocale;
if (locale && container.i18n.languages.has(locale)) return locale;

return 'en-US';
},
},
i18n: {
i18next: {
returnObjects: true,
},
defaultLanguageDirectory: '/var/tictactoe/languages',
defaultNS: 'index',
fetchLanguage: async (context: InternationalizationContext) => {
const locale = context.interactionGuildLocale || context.interactionLocale;
if (locale && container.i18n.languages.has(locale)) return locale;

return 'en-US';
},
},
Favna
Favna2y ago
And that directory is definitely correct? As an asside, what's your reason to not have the language files in the same folder as your bot? I.e. src/languages I don't know the exact methods but I recommend importing i18next and using its methods to analyze if languages get loaded properly. Don't forget that the plugin is merely a tiny wrapper around i18next itself so if something goes wrong with registering or such then i18next will be able to show it.
S222em
S222em2y ago
Typescript. I compile to another directory.
Favna
Favna2y ago
TS can include JSON files and move them to dist just fine You don't need a custom directory for that
S222em
S222em2y ago
I know, but only for JSON files that are imported directly from the code. It just ignores mine as I dont directly import them
Favna
Favna2y ago
Incorrect Assuming a root level tsconfig just set "include": ["src", "src/**/*.json"], And resolveJsonModule to true
S222em
S222em2y ago
Okay the "src/**/*.json" made it work Key is still not found. I will debug it further later. Got to go I found the issue
const { namespaces, languages } = await this.walkRootDirectory(this.languagesDirectory);
const userOptions = isFunction(this.options.i18next) ? this.options.i18next(namespaces, languages) : this.options.i18next;
const ignoreJSONStructure = userOptions?.ignoreJSONStructure ?? false;
const skipOnVariables = userOptions?.interpolation?.skipOnVariables ?? false;

i18next.use(Backend);
await i18next.init({
backend: this.backendOptions,
fallbackLng: this.options.defaultName ?? 'en-US',
initImmediate: false,
interpolation: {
escapeValue: false,
...userOptions?.interpolation,
skipOnVariables
},
load: 'all',
defaultNS: 'default',
ns: namespaces,
preload: languages,
...userOptions,
ignoreJSONStructure
});
const { namespaces, languages } = await this.walkRootDirectory(this.languagesDirectory);
const userOptions = isFunction(this.options.i18next) ? this.options.i18next(namespaces, languages) : this.options.i18next;
const ignoreJSONStructure = userOptions?.ignoreJSONStructure ?? false;
const skipOnVariables = userOptions?.interpolation?.skipOnVariables ?? false;

i18next.use(Backend);
await i18next.init({
backend: this.backendOptions,
fallbackLng: this.options.defaultName ?? 'en-US',
initImmediate: false,
interpolation: {
escapeValue: false,
...userOptions?.interpolation,
skipOnVariables
},
load: 'all',
defaultNS: 'default',
ns: namespaces,
preload: languages,
...userOptions,
ignoreJSONStructure
});
This is a piece of code from InternationalizationHandler.init(). It does not use the specified default NS in the options as typed. It does work if I provide them to the i18next option. defaultNS in this.options is ignored on i18next init. See example below
const client = new SapphireClient({
i18n: {
defaultNS: 'index', // Does not work
i18next: {
defaultNS: 'index' // Does work
}
});
const client = new SapphireClient({
i18n: {
defaultNS: 'index', // Does not work
i18next: {
defaultNS: 'index' // Does work
}
});
Favna
Favna2y ago
Hm The latter way is what I meant but I was on mobile so couldn't easily pull it up But the former way should've been blocked at least by TypeScript types Basically everything on the root i18n goes to the plugin itself and everything on i18n.i18next goes to i18next