Skip to content

Commit

Permalink
feat: warning if changing to locale without translations
Browse files Browse the repository at this point in the history
  • Loading branch information
Sv443 committed Jan 18, 2025
1 parent aa7adef commit 8f58c38
Show file tree
Hide file tree
Showing 6 changed files with 58 additions and 23 deletions.
3 changes: 2 additions & 1 deletion src/assets/translations/en-US.json
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,8 @@
"invalidValue": "Invalid ${settingName} specified: `${newValue}`${invalidHintSuffix}",
"success": "Successfully set the ${settingName} to `${newValue}`",
"error": "Couldn't set the ${settingName} due to an error: ${err}",
"localeInvalidHint": "Only the listed languages are supported."
"localeInvalidHint": "Only the listed languages are supported.",
"localeNotFoundWarning": "Translations for the locale `${localeName}` were not found.\nThe change has been saved because number formatting will still work, but all text will default to English.\n\nIf you would like to contribute to translations, please [join the support server.](${supportServerInviteUrl})"
},
"reset": {
"confirm": "Are you sure you want to reset the configuration?",
Expand Down
18 changes: 15 additions & 3 deletions src/commands/Config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { capitalize } from "@lib/text.ts";
import localesJson from "@assets/locales.json" with { type: "json" };
import type { Stringifiable } from "@src/types.ts";
import { registerCommandsForGuild } from "@lib/registry.ts";
import { getLocMap, tr, type TrKeyEn } from "@lib/translate.ts";
import { getLocMap, getRegisteredLanguages, tr, type TrKeyEn } from "@lib/translate.ts";
import { getEnvVar } from "@lib/env.ts";

//#region constants
Expand Down Expand Up @@ -275,6 +275,8 @@ export class ConfigCmd extends SlashCommand {
int[int.deferred || int.replied ? "editReply" : "reply"](useEmbedify(tr.for(await ConfigCmd.getGuildLocale(int), "errors.guildCfgInaccessible"), Col.Error));
}

//#region s:editCfgSett

/** Call to edit or view the passed configuration setting */
public static async editConfigSetting<
TCfgKey extends keyof GuildConfig,
Expand Down Expand Up @@ -311,12 +313,12 @@ export class ConfigCmd extends SlashCommand {
if(!cfg)
return await ConfigCmd.noConfigFound(int);

// TODO: check if new_value needs to be translated
const newValue = opt.options?.[0]?.options?.find(o => o.name === "new_value")?.value as TCfgValue | undefined;
const newValue = opt.options?.[0]?.options?.find(o => o.name === tr.for("en-US", "commands.config.names.subcmd.args.newValue"))?.value as TCfgValue | undefined;
if(typeof newValue === "undefined") {
const cfg = await em.findOne(GuildConfig, { id: int.guildId });
if(!cfg)
return await ConfigCmd.noConfigFound(int);

return int.editReply(useEmbedify(tr.for(locale, "commands.config.set.currentValue", {
settingName: tr.for(locale, settingNameTrKey),
newValue: getValueLabel(cfg[cfgProp] as TCfgValue, locale) ?? cfg[cfgProp],
Expand All @@ -337,6 +339,16 @@ export class ConfigCmd extends SlashCommand {
if(cfgProp === "locale" && !this.global)
await registerCommandsForGuild(int.guildId);

// if no translations exist for the new locale, warn the user
const localeChanged = locale !== newValue;
if(localeChanged && !getRegisteredLanguages().has(String(newValue)) && opt.options?.[0]?.name === getSCNames().locale){
const loc = localesJson.find(({ code }) => code === newValue);
return await int.editReply(useEmbedify(tr.for(locale, "commands.config.set.localeNotFoundWarning", {
localeName: loc ? `${loc.name} (${loc.nativeName})` : newValue,
supportServerInviteUrl: getEnvVar("SUPPORT_SERVER_INVITE_URL"),
}), Col.Warning));
}

return int.editReply(useEmbedify(tr.for(locale, "commands.config.set.success", {
settingName: tr.for(locale, settingNameTrKey),
newValue: getValueLabel(newValue, locale) ?? newValue,
Expand Down
28 changes: 17 additions & 11 deletions src/lib/registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,17 +88,23 @@ async function registerGuildCommands() {

/** Registers all commands for the specified guild in the Discord API - can also be called at runtime to add commands to new guilds */
export async function registerCommandsForGuild(guildId: string) {
const { signal, abort } = new AbortController(),
timeout = setTimeout(() => abort(), 10_000),
data = await rest.put(
Routes.applicationGuildCommands(clientId, guildId),
{
body: [...cmdInstances.entries()].map(([, cmd]) => cmd.builderJson),
signal,
},
);
clearTimeout(timeout);
return data;
try {
const ac = new AbortController(),
{ signal, abort } = ac,
timeout = setTimeout(() => abort(), 10_000),
data = await rest.put(
Routes.applicationGuildCommands(clientId, guildId),
{
body: [...cmdInstances.entries()].map(([, cmd]) => cmd.builderJson),
signal,
},
);
clearTimeout(timeout);
return data;
}
catch(err) {
console.error(`Error while registering commands for guild "${guildId}": ${err}`);
}
}

/** Registers all client events and their listeners */
Expand Down
5 changes: 5 additions & 0 deletions src/lib/translate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -411,6 +411,11 @@ export async function initTranslations(): Promise<void> {
tr.setFallbackLanguage(enName ?? defaultLocale);
}

/** Returns all registered languages */
export function getRegisteredLanguages() {
return new Set(Object.keys(trans));
}

//#region getLocMap

/** Returns a localization map for all locales where the given common translation key exists */
Expand Down
17 changes: 11 additions & 6 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ async function init() {
client.on(Events.Error, (err) => console.error(k.red("Client error:"), err));

process.on("unhandledRejection", (reason, promise) => {
console.error(k.red("Unhandled rejection at:"), promise, k.red("\nRejection reason:"), reason);
console.error(k.red("Unhandled Promise rejection:"), promise, k.red("\n\nRejection reason:"), reason);
});

console.log(k.blue(`${client.user?.displayName ?? client.user?.username} is ready.\n`));
Expand Down Expand Up @@ -90,18 +90,23 @@ async function checkGuilds(client: Client) {
const registeredGuilds = await em.findAll(GuildConfig);
const tasks: Promise<unknown | void>[] = [];

for(const guild of [...client.guilds.cache.values()])
!registeredGuilds.some(g => g.id === guild.id)
for(const { id } of [...client.guilds.cache.values()])
!registeredGuilds.find(g => g.id === id)
&& tasks.push(
em.persistAndFlush(new GuildConfig(guild.id)),
registerCommandsForGuild(guild.id),
em.persistAndFlush(new GuildConfig(id)),
registerCommandsForGuild(id),
);

for(const guild of registeredGuilds)
if(!client.guilds.cache.has(guild.id))
tasks.push(em.removeAndFlush(guild));

await Promise.allSettled(tasks);
try {
await Promise.allSettled(tasks);
}
catch(e) {
console.error(k.red("Couldn't check guilds:"), e);
}
}

init();
10 changes: 8 additions & 2 deletions src/models/GuildConfig.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,14 @@ export class GuildConfig {
}

static async ensureExists(id: string) {
const conf = await em.findOne(GuildConfig, { id });
!conf && await em.persistAndFlush(new GuildConfig(id));
let exists = false;
try {
exists = Boolean(await em.findOne(GuildConfig, { id }));
}
catch(e) {
void e;
}
!exists && await em.persistAndFlush(new GuildConfig(id));
}

@PrimaryKey({ type: "string", length: 24 })
Expand Down

0 comments on commit 8f58c38

Please # to comment.