push current translation support progress

This commit is contained in:
MathMan05 2024-10-31 22:58:37 -05:00
parent 602b16a0ef
commit a0d870c1b3
14 changed files with 243 additions and 195 deletions

View file

@ -6,6 +6,7 @@ import { User } from "./user.js";
import {guildjson} from "./jsontypes.js";
import { PermissionToggle } from "./role.js";
import { Permissions } from "./permissions.js";
import { I18n } from "./i18n.js";
class Bot{
readonly owner:Localuser;
readonly token:string;
@ -27,7 +28,7 @@ class Bot{
};
}
settings(){
const settings = new Settings("Bot Settings");
const settings = new Settings(I18n.getTranslation("botSettings"));
const botOptions = settings.addButton("Profile",{ltr:true});
const bot=new User(this.json,this.localuser);
{
@ -50,7 +51,7 @@ class Bot{
settingsRight.addHTMLArea(hypotheticalProfile);
const finput = settingsLeft.addFileInput(
"Upload pfp:",
I18n.getTranslation("uploadPfp"),
_=>{
if(file){
this.updatepfp(file);
@ -76,7 +77,7 @@ class Bot{
});
let bfile: undefined | File | null;
const binput = settingsLeft.addFileInput(
"Upload banner:",
I18n.getTranslation("uploadBanner"),
_=>{
if(bfile !== undefined){
this.updatebanner(bfile);
@ -102,7 +103,7 @@ class Bot{
});
let changed = false;
const pronounbox = settingsLeft.addTextInput(
"Pronouns",
I18n.getTranslation("pronouns"),
_=>{
if(newpronouns || newbio || changed){
this.updateProfile({
@ -119,7 +120,7 @@ class Bot{
newpronouns = _;
regen();
});
const bioBox = settingsLeft.addMDInput("Bio:", _=>{}, {
const bioBox = settingsLeft.addMDInput(I18n.getTranslation("bio"), _=>{}, {
initText: bot.bio.rawString,
});
bioBox.watchForChange(_=>{
@ -134,7 +135,7 @@ class Bot{
color = "transparent";
}
const colorPicker = settingsLeft.addColorInput(
"Profile color",
I18n.getTranslation("profileColor"),
_=>{},
{ initColor: color }
);
@ -148,7 +149,7 @@ class Bot{
}
{
const guildsettings=settings.addButton("Guilds");
guildsettings.addTitle("Guilds bot is in:");
guildsettings.addTitle(I18n.getTranslation("botGuilds"));
fetch(this.info.api+"/users/@me/guilds/",{
headers:this.headers
}).then(_=>_.json()).then((json:(guildjson["properties"])[])=>{
@ -187,8 +188,8 @@ class Bot{
content.onclick=()=>{
const guildsetting=guildsettings.addSubOptions(guild.name);
guildsetting.addHTMLArea(content);
guildsetting.addButtonInput("","Leave Guild",()=>{
if(confirm(`Are you sure you want to leave ${guild.name}?`)){
guildsetting.addButtonInput("",I18n.getTranslation("leaveGuild"),()=>{
if(confirm(I18n.getTranslation("confirmGuildLeave",guild.name))){
fetch(this.info.api+"/users/@me/guilds/"+guild.id,{
method:"DELETE",
headers:this.headers
@ -250,7 +251,7 @@ class Bot{
});
}
static InviteMaker(id:string,container:Form,info:Localuser["info"]){
const gen=container.addSubOptions("URL generator",{
const gen=container.addSubOptions(I18n.getTranslation("UrlGen"),{
noSubmit:true
});
const params = new URLSearchParams("");

View file

@ -15,6 +15,7 @@ import{ MarkDown }from"./markdown.js";
import{ Member }from"./member.js";
import { Voice } from "./voice.js";
import { User } from "./user.js";
import { I18n } from "./i18n.js";
declare global {
interface NotificationOptions {
@ -53,20 +54,20 @@ class Channel extends SnowFlake{
voice?:Voice;
bitrate:number=128000;
static setupcontextmenu(){
this.contextmenu.addbutton("Copy channel id", function(this: Channel){
this.contextmenu.addbutton(()=>I18n.getTranslation("channel.copyId"), function(this: Channel){
navigator.clipboard.writeText(this.id);
});
this.contextmenu.addbutton("Mark as read", function(this: Channel){
this.contextmenu.addbutton(()=>I18n.getTranslation("channel.markRead"), function(this: Channel){
this.readbottom();
});
this.contextmenu.addbutton("Settings", function(this: Channel){
this.contextmenu.addbutton(()=>I18n.getTranslation("channel.settings"), function(this: Channel){
this.generateSettings();
});
this.contextmenu.addbutton(
"Delete channel",
()=>I18n.getTranslation("channel.delete"),
function(this: Channel){
this.deleteChannel();
},
@ -77,7 +78,7 @@ class Channel extends SnowFlake{
);
this.contextmenu.addbutton(
"Make invite",
()=>I18n.getTranslation("channel.makeInvite"),
function(this: Channel){
this.createInvite();
},
@ -86,24 +87,6 @@ class Channel extends SnowFlake{
return this.hasPermission("CREATE_INSTANT_INVITE") && this.type !== 4;
}
);
/*
this.contextmenu.addbutton("Test button",function(){
this.localuser.ws.send(JSON.stringify({
"op": 14,
"d": {
"guild_id": this.guild.id,
"channels": {
[this.id]: [
[
0,
99
]
]
}
}
}))
},null);
/**/
}
createInvite(){
const div = document.createElement("div");
@ -148,20 +131,20 @@ class Channel extends SnowFlake{
update();
new Dialog([
"vdiv",
["title", "Invite people"],
["title", I18n.getTranslation("inviteOptions.title")],
["text", `to #${this.name} in ${this.guild.properties.name}`],
[
"select",
"Expire after:",
[
"30 Minutes",
"1 Hour",
"6 Hours",
"12 Hours",
"1 Day",
"7 Days",
"30 Days",
"Never",
I18n.getTranslation("inviteOptions.30m"),
I18n.getTranslation("inviteOptions.1h"),
I18n.getTranslation("inviteOptions.6h"),
I18n.getTranslation("inviteOptions.12h"),
I18n.getTranslation("inviteOptions.1d"),
I18n.getTranslation("inviteOptions.7d"),
I18n.getTranslation("inviteOptions.30d"),
I18n.getTranslation("inviteOptions.never"),
],
function(e: Event){
expires = [1800, 3600, 21600, 43200, 86400, 604800, 2592000, 0,][(e.srcElement as HTMLSelectElement).selectedIndex];
@ -174,13 +157,13 @@ class Channel extends SnowFlake{
"select",
"Max uses:",
[
"No limit",
"1 use",
"5 uses",
"10 uses",
"25 uses",
"50 uses",
"100 uses",
I18n.getTranslation("inviteOptions.noLimit"),
I18n.getTranslation("inviteOptions.limit","1"),
I18n.getTranslation("inviteOptions.limit","5"),
I18n.getTranslation("inviteOptions.limit","10"),
I18n.getTranslation("inviteOptions.limit","25"),
I18n.getTranslation("inviteOptions.limit","50"),
I18n.getTranslation("inviteOptions.limit","100"),
],
function(e: Event){
uses = [0, 1, 5, 10, 25, 50, 100][(e.srcElement as HTMLSelectElement).selectedIndex];
@ -193,7 +176,7 @@ class Channel extends SnowFlake{
}
generateSettings(){
this.sortPerms();
const settings = new Settings("Settings for " + this.name);
const settings = new Settings(I18n.getTranslation("channel.settingsFor",this.name));
{
const gensettings=settings.addButton("Settings");
const form=gensettings.addForm("",()=>{},{
@ -201,19 +184,20 @@ class Channel extends SnowFlake{
method: "PATCH",
headers: this.headers,
});
form.addTextInput("Name:","name",{initText:this.name});
form.addMDInput("Topic:","topic",{initText:this.topic});
form.addCheckboxInput("NSFW:","nsfw",{initState:this.nsfw});
form.addTextInput(I18n.getTranslation("channel.name:"),"name",{initText:this.name});
form.addMDInput(I18n.getTranslation("channel.topic:"),"topic",{initText:this.topic});
form.addCheckboxInput(I18n.getTranslation("channel.nsfw:"),"nsfw",{initState:this.nsfw});
if(this.type!==4){
const options=["voice", "text", "announcement"];
form.addSelect("Type:","type",options,{
form.addSelect("Type:","type",options.map(e=>I18n.getTranslation("channel."+e)),{
defaultIndex:options.indexOf({0:"text", 2:"voice", 5:"announcement", 4:"category" }[this.type] as string)
})
}
},options);
form.addPreprocessor((obj:any)=>{
obj.type={text: 0, voice: 2, announcement: 5, category: 4 }[obj.type as string]
})
}
}
const s1 = settings.addButton("Permissions");
s1.options.push(
new RoleList(
@ -308,10 +292,7 @@ class Channel extends SnowFlake{
this.permission_overwrites = new Map();
this.permission_overwritesar = [];
for(const thing of json.permission_overwrites){
if(
thing.id === "1182819038095799904" ||
thing.id === "1182820803700625444"
){
if(thing.id === "1182819038095799904" ||thing.id === "1182820803700625444"){
continue;
}
if(!this.permission_overwrites.has(thing.id)){
@ -406,10 +387,7 @@ class Channel extends SnowFlake{
return false;
}
get canMessage(): boolean{
if(
this.permission_overwritesar.length === 0 &&
this.hasPermission("MANAGE_CHANNELS")
){
if(this.permission_overwritesar.length === 0 &&this.hasPermission("MANAGE_CHANNELS")){
const role = this.guild.roles.find(_=>_.name === "@everyone");
if(role){
this.addRoleToPerms(role);
@ -445,6 +423,7 @@ class Channel extends SnowFlake{
position: number | undefined;
parent_id: string | undefined;
} = { id: thing.id, position: undefined, parent_id: undefined };
if(thing.position < position){
thing.position = thisthing.position = position + 1;
}
@ -652,12 +631,7 @@ class Channel extends SnowFlake{
return;
}
fetch(
this.info.api +
"/channels/" +
this.id +
"/messages/" +
this.lastmessageid +
"/ack",
this.info.api +"/channels/" + this.id + "/messages/" + this.lastmessageid + "/ack",
{
method: "POST",
headers: this.headers,
@ -768,7 +742,7 @@ class Channel extends SnowFlake{
if(this.replyingto){
replybox.innerHTML = "";
const span = document.createElement("span");
span.textContent = "Replying to " + this.replyingto.author.username;
span.textContent = I18n.getTranslation("replyingTo", this.replyingto.author.username);
const X = document.createElement("button");
X.onclick = _=>{
if(this.replyingto?.div){
@ -827,9 +801,7 @@ class Channel extends SnowFlake{
history.pushState(null, "", "/channels/" + this.guild_id + "/" + this.id);
this.localuser.pageTitle("#" + this.name);
const channelTopic = document.getElementById(
"channelTopic"
) as HTMLSpanElement;
const channelTopic = document.getElementById("channelTopic") as HTMLSpanElement;
if(this.topic){
channelTopic.innerHTML = new MarkDown(
this.topic,
@ -855,8 +827,7 @@ class Channel extends SnowFlake{
await this.buildmessages();
//loading.classList.remove("loading");
(document.getElementById("typebox") as HTMLDivElement).contentEditable =
"" + this.canMessage;
(document.getElementById("typebox") as HTMLDivElement).contentEditable =""+this.canMessage;
}
typingmap: Map<Member, number> = new Map();
async typingStart(typing: startTypingjson): Promise<void>{
@ -893,11 +864,7 @@ class Channel extends SnowFlake{
this.typingmap.delete(thing);
}
}
if(i > 1){
build += " are typing";
}else{
build += " is typing";
}
build=I18n.getTranslation("typing",i+"",build);
if(this.localuser.channelfocus === this){
if(showing){
typingtext.classList.remove("hidden");
@ -1013,12 +980,7 @@ class Channel extends SnowFlake{
}
await fetch(
this.info.api +
"/channels/" +
this.id +
"/messages?before=" +
id +
"&limit=100",
this.info.api + "/channels/" + this.id +"/messages?before=" + id + "&limit=100",
{
headers: this.headers,
}
@ -1099,8 +1061,7 @@ class Channel extends SnowFlake{
if(!removetitle){
const title = document.createElement("h2");
title.id = "removetitle";
title.textContent =
"No messages appear to be here, be the first to say something!";
title.textContent = I18n.getTranslation("noMessages");
title.classList.add("titlespace");
messages.append(title);
}
@ -1353,7 +1314,7 @@ class Channel extends SnowFlake{
noticontent ||= message.embeds[0]?.json.title;
noticontent ||= message.content.textContent;
}
noticontent ||= "Blank Message";
noticontent ||= I18n.getTranslation("blankMessage");
let imgurl: null | string = null;
const images = message.getimages();
if(images.length){

View file

@ -12,6 +12,7 @@ import{
import{ Permissions }from"./permissions.js";
import{ SnowFlake }from"./snowflake.js";
import{ Contextmenu }from"./contextmenu.js";
import { I18n } from "./i18n.js";
class Direct extends Guild{
declare channelids: { [key: string]: Group };
@ -99,24 +100,24 @@ dmPermissions.setPermission("SPEAK", 1);
dmPermissions.setPermission("STREAM", 1);
dmPermissions.setPermission("USE_VAD", 1);
// @ts-ignore
// @ts-ignore I need to look into this lol
class Group extends Channel{
user: User;
static contextmenu = new Contextmenu<Group, undefined>("channel menu");
static setupcontextmenu(){
this.contextmenu.addbutton("Copy DM id", function(this: Group){
this.contextmenu.addbutton(()=>I18n.getTranslation("DMs.copyId"), function(this: Group){
navigator.clipboard.writeText(this.id);
});
this.contextmenu.addbutton("Mark as read", function(this: Group){
this.contextmenu.addbutton(()=>I18n.getTranslation("DMs.markRead"), function(this: Group){
this.readbottom();
});
this.contextmenu.addbutton("Close DM", function(this: Group){
this.contextmenu.addbutton(()=>I18n.getTranslation("DMs.close"), function(this: Group){
this.deleteChannel();
});
this.contextmenu.addbutton("Copy user ID", function(){
this.contextmenu.addbutton(()=>I18n.getTranslation("user.copyId"), function(){
navigator.clipboard.writeText(this.user.id);
});
}
@ -179,10 +180,7 @@ class Group extends Channel{
const prom = this.infinite.delete();
history.pushState(null, "", "/channels/" + this.guild_id + "/" + this.id);
this.localuser.pageTitle("@" + this.name);
(document.getElementById("channelTopic") as HTMLElement).setAttribute(
"hidden",
""
);
(document.getElementById("channelTopic") as HTMLElement).setAttribute("hidden","");
const loading = document.getElementById("loadingdiv") as HTMLDivElement;
Channel.regenLoadingMessages();
@ -306,4 +304,5 @@ class Group extends Channel{
}
}
export{ Direct, Group };
Group.setupcontextmenu();
Group.setupcontextmenu()

View file

@ -4,6 +4,7 @@ import{ MarkDown }from"./markdown.js";
import{ embedjson, invitejson }from"./jsontypes.js";
import{ getapiurls, getInstances }from"./login.js";
import{ Guild }from"./guild.js";
import { I18n } from "./i18n.js";
class Embed{
type: string;
@ -296,8 +297,7 @@ guild as invitejson["guild"] & { info: { cdn: string } }
guildinfo.append(name);
const members = document.createElement("span");
members.innerText =
"#" + json.channel.name + " • Members: " + guild.member_count;
members.innerText = "#" + json.channel.name + " • Members: " + guild.member_count;
guildinfo.append(members);
members.classList.add("subtext");
iconrow.append(guildinfo);
@ -305,12 +305,12 @@ guild as invitejson["guild"] & { info: { cdn: string } }
div.append(iconrow);
const h2 = document.createElement("h2");
h2.textContent = `You've been invited by ${json.inviter.username}`;
h2.textContent = I18n.getTranslation("invite.invitedBy",json.inviter.username);
div.append(h2);
const button = document.createElement("button");
button.textContent = "Accept";
button.textContent = I18n.getTranslation("invite.accept");
if(this.localuser.info.api.startsWith(info.api) && this.localuser.guildids.has(guild.id)){
button.textContent = "Already joined";
button.textContent = I18n.getTranslation("invite.alreadyJoined");
button.disabled = true;
}
button.classList.add("acceptinvbutton");

View file

@ -2,6 +2,7 @@ import{ Contextmenu }from"./contextmenu.js";
import{ Guild }from"./guild.js";
import{ Localuser }from"./localuser.js";
//I need to recompile the emoji format for translation
class Emoji{
static emojis: {
name: string;
@ -158,13 +159,7 @@ class Emoji{
const img = document.createElement("img");
img.classList.add("pfp", "servericon", "emoji-server");
img.crossOrigin = "anonymous";
img.src =
localuser.info.cdn +
"/icons/" +
guild.properties.id +
"/" +
guild.properties.icon +
".png?size=48";
img.src = localuser.info.cdn+"/icons/"+guild.properties.id+"/"+guild.properties.icon+".png?size=48";
img.alt = "Server: " + guild.properties.name;
select.appendChild(img);
}else{

View file

@ -145,9 +145,7 @@ class File{
static filesizehuman(fsize: number){
const i = fsize == 0 ? 0 : Math.floor(Math.log(fsize) / Math.log(1024));
return(
Number((fsize / Math.pow(1024, i)).toFixed(2)) * 1 +
" " +
["Bytes", "Kilobytes", "Megabytes", "Gigabytes", "Terabytes"][i]
Number((fsize / Math.pow(1024, i)).toFixed(2)) * 1 + " " + ["Bytes", "Kilobytes", "Megabytes", "Gigabytes", "Terabytes"][i] // I don't think this changes across languages, correct me if I'm wrong
);
}
}

View file

@ -16,6 +16,7 @@ import{
rolesjson,
}from"./jsontypes.js";
import{ User }from"./user.js";
import { I18n } from "./i18n.js";
class Guild extends SnowFlake{
owner!: Localuser;
@ -38,20 +39,20 @@ class Guild extends SnowFlake{
members=new Set<Member>();
static contextmenu = new Contextmenu<Guild, undefined>("guild menu");
static setupcontextmenu(){
Guild.contextmenu.addbutton("Copy Guild id", function(this: Guild){
Guild.contextmenu.addbutton(()=>I18n.getTranslation("guild.copyId"), function(this: Guild){
navigator.clipboard.writeText(this.id);
});
Guild.contextmenu.addbutton("Mark as read", function(this: Guild){
Guild.contextmenu.addbutton(()=>I18n.getTranslation("guild.markRead"), function(this: Guild){
this.markAsRead();
});
Guild.contextmenu.addbutton("Notifications", function(this: Guild){
Guild.contextmenu.addbutton(()=>I18n.getTranslation("guild.notifications"), function(this: Guild){
this.setnotifcation();
});
Guild.contextmenu.addbutton(
"Leave guild",
()=>I18n.getTranslation("guild.leave"),
function(this: Guild){
this.confirmleave();
},
@ -62,7 +63,7 @@ class Guild extends SnowFlake{
);
Guild.contextmenu.addbutton(
"Delete guild",
()=>I18n.getTranslation("guild.delete"),
function(this: Guild){
this.confirmDelete();
},
@ -73,13 +74,13 @@ class Guild extends SnowFlake{
);
Guild.contextmenu.addbutton(
"Create invite",
()=>I18n.getTranslation("guild.makeInvite"),
function(this: Guild){},
null,
_=>true,
_=>false
);
Guild.contextmenu.addbutton("Settings", function(this: Guild){
Guild.contextmenu.addbutton(()=>I18n.getTranslation("guild.settings"), function(this: Guild){
this.generateSettings();
});
/* -----things left for later-----
@ -94,28 +95,28 @@ class Guild extends SnowFlake{
*/
}
generateSettings(){
const settings = new Settings("Settings for " + this.properties.name);
const settings = new Settings(I18n.getTranslation("guild.settingsFor",this.properties.name));
{
const overview = settings.addButton("Overview");
const overview = settings.addButton(I18n.getTranslation("guild.overview"));
const form = overview.addForm("", _=>{}, {
headers: this.headers,
traditionalSubmit: true,
fetchURL: this.info.api + "/guilds/" + this.id,
method: "PATCH",
});
form.addTextInput("Name:", "name", { initText: this.properties.name });
form.addTextInput(I18n.getTranslation("guild.name:"), "name", { initText: this.properties.name });
form.addMDInput("Description:", "description", {
initText: this.properties.description,
});
form.addFileInput("Banner:", "banner", { clear: true });
form.addFileInput("Icon:", "icon", { clear: true });
form.addFileInput(I18n.getTranslation("guild.banner:"), "banner", { clear: true });
form.addFileInput(I18n.getTranslation("guild.icon:"), "icon", { clear: true });
let region = this.properties.region;
if(!region){
region = "";
}
form.addTextInput("Region:", "region", { initText: region });
form.addTextInput(I18n.getTranslation("guild.region:"), "region", { initText: region });
}
const s1 = settings.addButton("Roles");
const s1 = settings.addButton(I18n.getTranslation("guild.roles"));
const permlist: [Role, Permissions][] = [];
for(const thing of this.roles){
permlist.push([thing, thing.permissions]);
@ -261,14 +262,15 @@ class Guild extends SnowFlake{
}
setnotifcation(){
let noti = this.message_notifications;
const options=["all", "onlyMentions", "none"].map(e=>I18n.getTranslation("guild."+e))
const notiselect = new Dialog([
"vdiv",
[
"radio",
"select notifications type",
["all", "only mentions", "none"],
function(e: string /* "all" | "only mentions" | "none" */){
noti = ["all", "only mentions", "none"].indexOf(e);
I18n.getTranslation("guild.selectnoti"),
options,
function(e: string){
noti = options.indexOf(e);
},
noti,
],
@ -294,13 +296,13 @@ class Guild extends SnowFlake{
confirmleave(){
const full = new Dialog([
"vdiv",
["title", "Are you sure you want to leave?"],
["title", I18n.getTranslation("guild.confirmLeave")],
[
"hdiv",
[
"button",
"",
"Yes, I'm sure",
I18n.getTranslation("yesLeave"),
(_: any)=>{
this.leave().then(_=>{
full.hide();
@ -310,7 +312,7 @@ class Guild extends SnowFlake{
[
"button",
"",
"Nevermind",
I18n.getTranslation("noLeave"),
(_: any)=>{
full.hide();
},
@ -467,11 +469,11 @@ class Guild extends SnowFlake{
"vdiv",
[
"title",
"Are you sure you want to delete " + this.properties.name + "?",
I18n.getTranslation("guild.confirmDelete",this.properties.name)
],
[
"textbox",
"Name of server:",
I18n.getTranslation("serverName"),
"",
function(this: HTMLInputElement){
confirmname = this.value;
@ -482,7 +484,7 @@ class Guild extends SnowFlake{
[
"button",
"",
"Yes, I'm sure",
I18n.getTranslation("yesDelete"),
(_: any)=>{
console.log(confirmname);
if(confirmname !== this.properties.name){
@ -496,7 +498,7 @@ class Guild extends SnowFlake{
[
"button",
"",
"Nevermind",
I18n.getTranslation("noDelete"),
(_: any)=>{
full.hide();
},
@ -638,22 +640,23 @@ class Guild extends SnowFlake{
createchannels(func = this.createChannel){
let name = "";
let category = 0;
const options=["voice", "text", "announcement"].map(e=>I18n.getTranslation("channel."+e));
const numbers=[2,0,5]
const channelselect = new Dialog([
"vdiv",
[
"radio",
"select channel type",
["voice", "text", "announcement"],
I18n.getTranslation("channel.selectType"),
options,
function(radio: string){
console.log(radio);
category =
{ text: 0, voice: 2, announcement: 5, category: 4 }[radio] || 0;
category = numbers[options.indexOf(radio)] || 0;
},
1,
],
[
"textbox",
"Name of channel",
I18n.getTranslation("channel.selectName"),
"",
function(this: HTMLInputElement){
name = this.value;
@ -662,7 +665,7 @@ class Guild extends SnowFlake{
[
"button",
"",
"submit",
I18n.getTranslation("submit"),
()=>{
console.log(name, category);
func.bind(this)(name, category);
@ -679,7 +682,7 @@ class Guild extends SnowFlake{
"vdiv",
[
"textbox",
"Name of category",
I18n.getTranslation("channel.selectCatName"),
"",
function(this: HTMLInputElement){
name = this.value;
@ -688,7 +691,7 @@ class Guild extends SnowFlake{
[
"button",
"",
"submit",
I18n.getTranslation("submit"),
function(this:Guild){
console.log(name, category);
this.createChannel(name, category);

View file

@ -1,3 +1,4 @@
import { I18n } from "./i18n.js";
import{ mobile }from"./login.js";
console.log(mobile);
const serverbox = document.getElementById("instancebox") as HTMLDivElement;
@ -5,7 +6,7 @@ const serverbox = document.getElementById("instancebox") as HTMLDivElement;
fetch("/instances.json")
.then(_=>_.json())
.then(
(
async (
json: {
name: string;
description?: string;
@ -24,6 +25,7 @@ fetch("/instances.json")
};
}[]
)=>{
await I18n.done;
console.warn(json);
for(const instance of json){
if(instance.display === false){
@ -66,11 +68,11 @@ fetch("/instances.json")
const stats = document.createElement("div");
stats.classList.add("flexltr");
const span = document.createElement("span");
span.innerText = `Uptime: All time: ${Math.round(
span.innerText = I18n.getTranslation("home.uptimeStats",Math.round(
instance.uptime.alltime * 100
)}% This week: ${Math.round(
)+"",Math.round(
instance.uptime.weektime * 100
)}% Today: ${Math.round(instance.uptime.daytime * 100)}%`;
)+"",Math.round(instance.uptime.daytime * 100)+"")
stats.append(span);
statbox.append(stats);
}
@ -79,7 +81,7 @@ fetch("/instances.json")
if(instance.online){
window.location.href = "/register.html?instance=" + encodeURI(instance.name);
}else{
alert("Instance is offline, can't connect");
alert(I18n.getTranslation("home.warnOffiline"));
}
};
serverbox.append(div);

View file

@ -105,4 +105,5 @@ class I18n{
}
}
}
I18n.create("/translations/en.json","en")
export{I18n};

View file

@ -4,6 +4,7 @@ import{ mobile, getBulkUsers, setTheme, Specialuser }from"./login.js";
import{ MarkDown }from"./markdown.js";
import{ Message }from"./message.js";
import{ File }from"./file.js";
import { I18n } from "./i18n.js";
(async ()=>{
async function waitForLoad(): Promise<void>{
@ -13,7 +14,7 @@ import{ File }from"./file.js";
}
await waitForLoad();
await I18n.done
const users = getBulkUsers();
if(!users.currentuser){
window.location.href = "/login.html";
@ -74,7 +75,7 @@ import{ File }from"./file.js";
const switchAccountDiv = document.createElement("div");
switchAccountDiv.classList.add("switchtable");
switchAccountDiv.textContent = "Switch accounts ⇌";
switchAccountDiv.textContent = I18n.getTranslation("switchAccounts");
switchAccountDiv.addEventListener("click", ()=>{
window.location.href = "/login.html";
});
@ -93,9 +94,7 @@ import{ File }from"./file.js";
showAccountSwitcher();
});
const switchAccountsElement = document.getElementById(
"switchaccounts"
) as HTMLDivElement;
const switchAccountsElement = document.getElementById("switchaccounts") as HTMLDivElement;
switchAccountsElement.addEventListener("click", event=>{
event.stopImmediatePropagation();
showAccountSwitcher();
@ -115,14 +114,13 @@ import{ File }from"./file.js";
});
}catch(e){
console.error(e);
(document.getElementById("load-desc") as HTMLSpanElement).textContent =
"Account unable to start";
(document.getElementById("load-desc") as HTMLSpanElement).textContent = I18n.getTranslation("accountNotStart");
thisUser = new Localuser(-1);
}
const menu = new Contextmenu("create rightclick");
const menu = new Contextmenu<void,void>("create rightclick");
menu.addbutton(
"Create channel",
I18n.getTranslation("channel.createChannel"),
()=>{
if(thisUser.lookingguild){
thisUser.lookingguild.createchannels();
@ -133,7 +131,7 @@ import{ File }from"./file.js";
);
menu.addbutton(
"Create category",
I18n.getTranslation("channel.createCatagory"),
()=>{
if(thisUser.lookingguild){
thisUser.lookingguild.createcategory();
@ -143,15 +141,9 @@ import{ File }from"./file.js";
()=>thisUser.isAdmin()
);
menu.bindContextmenu(
document.getElementById("channels") as HTMLDivElement,
0,
0
);
menu.bindContextmenu(document.getElementById("channels") as HTMLDivElement);
const pasteImageElement = document.getElementById(
"pasteimage"
) as HTMLDivElement;
const pasteImageElement = document.getElementById("pasteimage") as HTMLDivElement;
let replyingTo: Message | null = null;
async function handleEnter(event: KeyboardEvent): Promise<void>{

View file

@ -65,7 +65,6 @@ class Localuser{
"Content-type": "application/json; charset=UTF-8",
Authorization: this.userinfo.token,
};
I18n.create("/translations/en.json","en")
}
async gottenReady(ready: readyjson): Promise<void>{
await I18n.done;

View file

@ -56,13 +56,13 @@ class Message extends SnowFlake{
Message.setupcmenu();
}
static setupcmenu(){
Message.contextmenu.addbutton(I18n.getTranslation.bind(I18n,"copyrawtext"), function(this: Message){
Message.contextmenu.addbutton(()=>I18n.getTranslation("copyrawtext"), function(this: Message){
navigator.clipboard.writeText(this.content.rawString);
});
Message.contextmenu.addbutton(I18n.getTranslation.bind(I18n,"reply"), function(this: Message){
Message.contextmenu.addbutton(()=>I18n.getTranslation("reply"), function(this: Message){
this.channel.setReplying(this);
});
Message.contextmenu.addbutton(I18n.getTranslation.bind(I18n,"copymessageid"), function(this: Message){
Message.contextmenu.addbutton(()=>I18n.getTranslation("copymessageid"), function(this: Message){
navigator.clipboard.writeText(this.id);
});
Message.contextmenu.addsubmenu(

View file

@ -938,15 +938,18 @@ class Form implements OptionsElement<object>{
(this.button.deref() as HTMLElement).hidden=false;
}
}
selectMap=new WeakMap<SelectInput,string[]>();
addSelect(
label: string,
formName: string,
selections: string[],
{ defaultIndex = 0, required = false } = {}
{ defaultIndex = 0, required = false}={},
correct:string[]=selections
){
const select = this.options.addSelect(label, _=>{}, selections, {
defaultIndex,
});
this.selectMap.set(select,correct);
this.names.set(formName, select);
if(required){
this.required.add(select);
@ -1110,7 +1113,7 @@ class Form implements OptionsElement<object>{
if(thing === "")continue;
const input = this.names.get(thing) as OptionsElement<any>;
if(input instanceof SelectInput){
(build as any)[thing] = input.options[input.value];
(build as any)[thing] = (this.selectMap.get(input) as string[])[input.value];
continue;
}else if(input instanceof FileInput){
const options = this.fileOptions.get(input);

View file

@ -122,7 +122,101 @@
"no":"No",
"todayAt":"Today at $1",
"yesterdayAt":"Yesterday at $1",
"otherAt":"$1 at $2"
"otherAt":"$1 at $2",
"botSettings":"Bot Settings",
"uploadPfp":"Upload pfp:",
"uploadBanner":"Upload banner:",
"pronouns":"Pronouns:",
"bio":"Bio:",
"profileColor":"Profile color",
"botGuilds":"Guilds bot is in:",
"leaveGuild":"Leave Guild",
"confirmGuildLeave":"Are you sure you want to leave $1",
"UrlGen":"URL generator",
"typing":"$2 {{PLURAL:$1|are|is}} typing",
"noMessages":"No messages appear to be here, be the first to say something!",
"blankMessage":"Blank Message",
"channel":{
"copyId":"Copy channel id",
"markRead":"Mark as read",
"settings":"Settings",
"delete":"Delete channel",
"makeInvite":"Make invite",
"settingsFor":"Settings for $1",
"voice":"Voice",
"text":"Text",
"announcement":"Announcements",
"name:":"Name:",
"topic:":"Topic:",
"nsfw:":"NSFW:",
"selectType":"Select channel type",
"selectName":"Name of channel",
"selectCatName":"Name of channel",
"createChannel":"Create channel",
"createCatagory":"Create category"
},
"switchAccounts":"Switch accounts ⇌",
"accountNotStart":"Account unable to start",
"home":{
"uptimeStats":"Uptime: \n All time: $1\nThis week: $2\nToday: $3",
"warnOffiline":"Instance is offline, can't connect"
},
"submit":"submit",
"guild":{
"copyId":"Copy guild id",
"markRead":"Mark as read",
"notifications":"Notifications",
"leave":"Leave guild",
"settings":"Settings",
"delete":"Delete guild",
"makeInvite":"Make invite",
"settingsFor":"Settings for $1",
"name:":"Name:",
"topic:":"Topic:",
"icon:":"Icon:",
"overview":"Overview",
"banner:":"Banner:",
"region:":"Region:",
"roles":"Roles",
"selectnoti":"Select notifications type",
"all":"all",
"onlyMentions":"only mentions",
"none":"node",
"confirmLeave":"Are you sure you want to leave?",
"yesLeave":"Yes, I'm sure",
"noLeave":"Nevermind",
"confirmDelete":"Are you sure you want to delete $1?",
"serverName":"Name of server:",
"yesDelete":"Yes, I'm sure",
"noDelete":"Nevermind"
},
"inviteOptions":{
"title":"Invite People",
"30m":"30 Minutes",
"1h":"1 Hour",
"6h":"6 Hours",
"12h":"12 Hours",
"1d":"1 Day",
"7d":"7 Days",
"30d":"30 Days",
"never":"Never",
"limit":"$1 {{PLURAL:$1|use|uses}}",
"noLimit":"No limit"
},
"invite":{
"invitedBy":"You've been invited by $1",
"alreadyJoined":"Already joined",
"accept":"Accept"
},
"replyingTo":"Replying to $1",
"DMs":{
"copyId":"Copy DM id",
"markRead":"Mark as read",
"close":"Close DM"
},
"user":{
"copyId":"Copy user ID"
}
},
"ru": "./ru.json"
}