diff --git a/src/webpage/i18n.ts b/src/webpage/i18n.ts index af21a88..6a2f533 100644 --- a/src/webpage/i18n.ts +++ b/src/webpage/i18n.ts @@ -36,7 +36,7 @@ class I18n{ for(const json of this.translations){ let jsont:string|translation=json; for(const thing of path){ - if(typeof jsont !== "string" ){ + if(typeof jsont !== "string" && jsont!==undefined){ jsont=jsont[thing]; }else{ diff --git a/src/webpage/localuser.ts b/src/webpage/localuser.ts index 76a37aa..ba03042 100644 --- a/src/webpage/localuser.ts +++ b/src/webpage/localuser.ts @@ -953,7 +953,7 @@ class Localuser{ content.innerHTML = ""; const title = document.createElement("h2"); - title.textContent = I18n.getTranslation("guild.disoveryTitle"); + title.textContent = I18n.getTranslation("guild.disoveryTitle",json.guilds.length+""); content.appendChild(title); const guilds = document.createElement("div"); @@ -1365,7 +1365,7 @@ class Localuser{ ); form.addTextInput(I18n.getTranslation("lcoaluser.newDiscriminator"), "discriminator"); }); - security.addButtonInput("", I18n.getTranslation("lcoaluser.changeEmail"), ()=>{ + security.addButtonInput("", I18n.getTranslation("localuser.changeEmail"), ()=>{ const form = security.addSubForm( I18n.getTranslation("lcoaluser.changeEmail"), _=>{ @@ -1401,9 +1401,9 @@ class Localuser{ } form.addTextInput(I18n.getTranslation("localuser.newUsername"), "username"); }); - security.addButtonInput("", "Change password", ()=>{ + security.addButtonInput("", I18n.getTranslation("localuser.changePassword"), ()=>{ const form = security.addSubForm( - "Change Password", + I18n.getTranslation("localuser.changePassword"), _=>{ security.returnFromSub(); }, @@ -1413,13 +1413,13 @@ class Localuser{ method: "PATCH", } ); - form.addTextInput("Old password:", "password", { password: true }); + form.addTextInput(I18n.getTranslation("localuser.oldPassword:"), "password", { password: true }); if(this.mfa_enabled){ - form.addTextInput("Code:", "code"); + form.addTextInput(I18n.getTranslation("localuser.2faCode"), "code"); } let in1 = ""; let in2 = ""; - form.addTextInput("New password:", "").watchForChange(text=>{ + form.addTextInput(I18n.getTranslation("localuser.newPassword:"), "").watchForChange(text=>{ in1 = text; }); const copy = form.addTextInput("New password again:", ""); @@ -1430,7 +1430,7 @@ class Localuser{ if(in1 === in2){ return in1; }else{ - throw new FormError(copy, "Passwords don't match"); + throw new FormError(copy, I18n.getTranslation("localuser.PasswordsNoMatch")); } }); }); @@ -1473,8 +1473,7 @@ class Localuser{ }); }else{ container.classList.add("disabled"); - container.title = - "This connection has been disabled server-side."; + container.title = I18n.getTranslation("localuser.PasswordsNoMatch"); } connectionContainer.appendChild(container); @@ -1483,16 +1482,16 @@ class Localuser{ connections.addHTMLArea(connectionContainer); } { - const devPortal = settings.addButton("Developer Portal"); + const devPortal = settings.addButton(I18n.getTranslation("localuser.devPortal")); fetch(this.info.api + "/teams", { headers: this.headers, }).then(async (teamsRes)=>{ const teams = await teamsRes.json(); - devPortal.addButtonInput("", "Create application", ()=>{ + devPortal.addButtonInput("", I18n.getTranslation("localuser.createApp"), ()=>{ const form = devPortal.addSubForm( - "Create application", + I18n.getTranslation("localuser.createApp"), (json: any)=>{ if(json.message) form.error("name", json.message); else{ @@ -1509,7 +1508,7 @@ class Localuser{ form.addTextInput("Name:", "name", { required: true }); form.addSelect( - "Team:", + I18n.getTranslation("localuser.team:"), "team_id", ["Personal", ...teams.map((team: { name: string })=>team.name)], { @@ -1583,16 +1582,16 @@ class Localuser{ headers:this.headers, traditionalSubmit:true }); - form.addTextInput("Application name:","name",{initText:json.name}); - form.addMDInput("Description:","description",{initText:json.description}); + form.addTextInput(I18n.getTranslation("localuser.appName"),"name",{initText:json.name}); + form.addMDInput(I18n.getTranslation("localuser.description"),"description",{initText:json.description}); form.addFileInput("Icon:","icon"); - form.addTextInput("Privacy policy URL:","privacy_policy_url",{initText:json.privacy_policy_url}); - form.addTextInput("Terms of Service URL:","terms_of_service_url",{initText:json.terms_of_service_url}); - form.addCheckboxInput("Make bot publicly inviteable?","bot_public",{initState:json.bot_public}); - form.addCheckboxInput("Require code grant to invite the bot?","bot_require_code_grant",{initState:json.bot_require_code_grant}); - form.addButtonInput("",(json.bot ? "Manage" : "Add")+" bot",async ()=>{ + form.addTextInput(I18n.getTranslation("localuser.privacyPolcyURL"),"privacy_policy_url",{initText:json.privacy_policy_url}); + form.addTextInput(I18n.getTranslation("localuser.TOSURL"),"terms_of_service_url",{initText:json.terms_of_service_url}); + form.addCheckboxInput(I18n.getTranslation("localuser.publicAvaliable"),"bot_public",{initState:json.bot_public}); + form.addCheckboxInput(I18n.getTranslation("localuser.requireCode"),"bot_require_code_grant",{initState:json.bot_require_code_grant}); + form.addButtonInput("",I18n.getTranslation("localuser."+(json.bot?"manageBot":"addBot")),async ()=>{ if(!json.bot){ - if(!confirm("Are you sure you want to add a bot to this application? There's no going back.")){ + if(!confirm(I18n.getTranslation("localuser.confirmAddBot"))){ return; } const updateRes = await fetch( @@ -1614,19 +1613,19 @@ class Localuser{ }); const json = await res.json(); if(!json.bot){ - return alert("For some reason, this application doesn't have a bot (yet)."); + return alert(I18n.getTranslation("localuser.confuseNoBot")); } const bot:mainuserjson=json.bot; - const form=container.addSubForm("Editing bot "+bot.username,out=>{console.log(out)},{ + const form=container.addSubForm(I18n.getTranslation("localuser.editingBot",bot.username),out=>{console.log(out)},{ method:"PATCH", fetchURL:this.info.api + "/applications/" + appId + "/bot", headers:this.headers, traditionalSubmit:true }); - form.addTextInput("Bot username:","username",{initText:bot.username}); - form.addFileInput("Bot avatar:","avatar"); - form.addButtonInput("","Reset Token",async ()=>{ - if(!confirm("Are you sure you want to reset the bot token? Your bot will stop working until you update it.")){ + form.addTextInput(I18n.getTranslation("localuser.botUsername"),"username",{initText:bot.username}); + form.addFileInput(I18n.getTranslation("localuser.botAvatar"),"avatar"); + form.addButtonInput("",I18n.getTranslation("localuser.resetToken"),async ()=>{ + if(!confirm(I18n.getTranslation("localuser.confirmReset"))){ return; } const updateRes = await fetch( @@ -1637,27 +1636,27 @@ class Localuser{ } ); const updateJSON = await updateRes.json(); - text.setText("Token: "+updateJSON.token); + text.setText(I18n.getTranslation("localuser.tokenDisplay",updateJSON.token)); this.botTokens.set(appId,updateJSON.token); if(this.perminfo.applications[appId]){ this.perminfo.applications[appId]=updateJSON.token; this.userinfo.updateLocal(); } }); - const text=form.addText(this.botTokens.has(appId)?"Token: "+this.botTokens.get(appId):"Token: *****************"); + const text=form.addText(I18n.getTranslation("localuser.tokenDisplay",this.botTokens.has(appId)?this.botTokens.get(appId) as string:"*****************") ); const check=form.addOptions("",{noSubmit:true}); if(!this.perminfo.applications){ this.perminfo.applications={}; this.userinfo.updateLocal(); } - const checkbox=check.addCheckboxInput("Save token to localStorage",()=>{},{initState:!!this.perminfo.applications[appId]}); + const checkbox=check.addCheckboxInput(I18n.getTranslation("localuser.saveToken"),()=>{},{initState:!!this.perminfo.applications[appId]}); checkbox.watchForChange(_=>{ if(_){ if(this.botTokens.has(appId)){ this.perminfo.applications[appId]=this.botTokens.get(appId); this.userinfo.updateLocal(); }else{ - alert("Don't know token so can't save it to localStorage, sorry"); + alert(I18n.getTranslation("localuser.noToken")); checkbox.setState(false); } }else{ @@ -1665,14 +1664,14 @@ class Localuser{ this.userinfo.updateLocal(); } }); - form.addButtonInput("","Advanced Bot Settings",()=>{ + form.addButtonInput("",I18n.getTranslation("localuser.advancedBot"),()=>{ const token=this.botTokens.get(appId); if(token){ const botc=new Bot(bot,token,this); botc.settings(); } }); - form.addButtonInput("","Bot Invite Creator",()=>{ + form.addButtonInput("",I18n.getTranslation("localuser.botInviteCreate"),()=>{ Bot.InviteMaker(appId,form,this.info); }) } @@ -1849,11 +1848,11 @@ class Localuser{ const dialog = new Dialog([ "vdiv", - ["title", "Instance stats: " + this.instancePing.name], - ["text", "Registered users: " + json.counts.user], - ["text", "Servers: " + json.counts.guild], - ["text", "Messages: " + json.counts.message], - ["text", "Members: " + json.counts.members], + ["title", I18n.getTranslation("instanceStats.name",this.instancePing.name) ], + ["text", I18n.getTranslation("instanceStats.users",json.counts.user)], + ["text", I18n.getTranslation("instanceStats.servers",json.counts.guild)], + ["text", I18n.getTranslation("instanceStats.messages",json.counts.message)], + ["text", I18n.getTranslation("instanceStats.members",json.counts.members)], ]); dialog.show(); } diff --git a/src/webpage/login.ts b/src/webpage/login.ts index a1f765a..1804f09 100644 --- a/src/webpage/login.ts +++ b/src/webpage/login.ts @@ -1,4 +1,5 @@ import{ Dialog }from"./dialog.js"; +import { I18n } from "./i18n.js"; const mobile = /iPhone|iPad|iPod|Android/i.test(navigator.userAgent); const iOS = /iPhone|iPad|iPod/i.test(navigator.userAgent); @@ -338,7 +339,7 @@ async function getapiurls(str: string): Promise< async function checkInstance(instance?: string){ const verify = document.getElementById("verify"); try{ - verify!.textContent = "Checking Instance"; + verify!.textContent = I18n.getTranslation("login.checking"); const instanceValue = instance || (instancein as HTMLInputElement).value; const instanceinfo = (await getapiurls(instanceValue)) as { wellknown: string; @@ -351,7 +352,7 @@ async function checkInstance(instance?: string){ if(instanceinfo){ instanceinfo.value = instanceValue; localStorage.setItem("instanceinfo", JSON.stringify(instanceinfo)); - verify!.textContent = "Instance is all good"; + verify!.textContent = I18n.getTranslation("login.allGood"); // @ts-ignore if(checkInstance.alt){ // @ts-ignore @@ -362,11 +363,11 @@ async function checkInstance(instance?: string){ verify!.textContent = ""; }, 3000); }else{ - verify!.textContent = "Invalid Instance, try again"; + verify!.textContent = I18n.getTranslation("login.invalid"); } }catch{ console.log("catch"); - verify!.textContent = "Invalid Instance, try again"; + verify!.textContent = I18n.getTranslation("login.invalid"); } } @@ -374,7 +375,7 @@ if(instancein){ console.log(instancein); instancein.addEventListener("keydown", ()=>{ const verify = document.getElementById("verify"); - verify!.textContent = "Waiting to check Instance"; + verify!.textContent = I18n.getTranslation("login.waiting"); if(timeout !== null && typeof timeout !== "string"){ clearTimeout(timeout); } @@ -442,7 +443,7 @@ async function login(username: string, password: string, captcha: string){ let onetimecode = ""; new Dialog([ "vdiv", - ["title", "2FA code:"], + ["title", I18n.getTranslation("2faCode")], [ "textbox", "", @@ -455,7 +456,7 @@ async function login(username: string, password: string, captcha: string){ [ "button", "", - "Submit", + I18n.getTranslation("submit"), function(){ fetch(api + "/auth/mfa/totp", { method: "POST", diff --git a/src/webpage/markdown.ts b/src/webpage/markdown.ts index 75a4635..ce02f07 100644 --- a/src/webpage/markdown.ts +++ b/src/webpage/markdown.ts @@ -2,6 +2,7 @@ import{ Channel }from"./channel.js"; import{ Dialog }from"./dialog.js"; import{ Emoji }from"./emoji.js"; import{ Guild }from"./guild.js"; +import { I18n } from "./i18n.js"; import{ Localuser }from"./localuser.js"; import{ Member }from"./member.js"; @@ -9,8 +10,8 @@ class MarkDown{ txt: string[]; keep: boolean; stdsize: boolean; - owner: Localuser | Channel; - info: Localuser["info"]; + owner: Localuser | Channel|void; + info: Localuser["info"]|void=undefined; constructor( text: string | string[], owner: MarkDown["owner"], @@ -24,7 +25,9 @@ class MarkDown{ if(this.txt === undefined){ this.txt = []; } - this.info = owner.info; + if(owner){ + this.info = owner.info; + } this.keep = keep; this.owner = owner; this.stdsize = stdsize; @@ -32,9 +35,10 @@ class MarkDown{ get localuser(){ if(this.owner instanceof Localuser){ return this.owner; - }else{ + }else if(this.owner){ return this.owner.localuser; } + return null; } get rawString(){ return this.txt.join(""); @@ -437,7 +441,7 @@ txt[j + 1] === undefined) continue; } } - if(txt[i] === "<" && (txt[i + 1] === "@" || txt[i + 1] === "#")){ + if((txt[i] === "<" && (txt[i + 1] === "@" || txt[i + 1] === "#"))&&this.localuser){ let id = ""; let j = i + 2; const numbers = new Set(["0","1","2","3","4","5","6","7","8","9",]); @@ -485,6 +489,7 @@ txt[j + 1] === undefined) mention.textContent = `#${channel.name}`; if(!keep){ mention.onclick = _=>{ + if(!this.localuser) return; this.localuser.goToChannel(id); }; } @@ -586,7 +591,7 @@ txt[j + 1] === undefined) if( txt[i] === "<" && - (txt[i + 1] === ":" || (txt[i + 1] === "a" && txt[i + 2] === ":")) + (txt[i + 1] === ":" || (txt[i + 1] === "a" && txt[i + 2] === ":")&&this.owner) ){ let found = false; const build = txt[i + 1] === "a" ? ["<", "a", ":"] : ["<", ":"]; @@ -609,6 +614,7 @@ txt[j + 1] === undefined) const isEmojiOnly = txt.join("").trim() === buildjoin.trim(); const owner = this.owner instanceof Channel ? this.owner.guild : this.owner; + if(!owner) continue; const emoji = new Emoji( { name: buildjoin, id: parts[2], animated: Boolean(parts[1]) }, owner @@ -765,20 +771,18 @@ txt[j + 1] === undefined) }else{ const full: Dialog = new Dialog([ "vdiv", - ["title", "You're leaving Spacebar"], + ["title", I18n.getTranslation("leaving")], [ "text", - "You're going to " + - Url.host + - ". Are you sure you want to go there?", + I18n.getTranslation("goingToURL",Url.host) ], [ "hdiv", - ["button", "", "Nevermind", (_: any)=>full.hide()], + ["button", "", I18n.getTranslation("nevermind"), (_: any)=>full.hide()], [ "button", "", - "Go there", + I18n.getTranslation("goThere"), (_: any)=>{ open(); full.hide(); @@ -787,7 +791,7 @@ txt[j + 1] === undefined) [ "button", "", - "Go there and trust in the future", + I18n.getTranslation("goThereTrust"), (_: any)=>{ open(); full.hide(); diff --git a/src/webpage/member.ts b/src/webpage/member.ts index 4c49ecf..9c40a11 100644 --- a/src/webpage/member.ts +++ b/src/webpage/member.ts @@ -4,6 +4,7 @@ import{ Guild }from"./guild.js"; import{ SnowFlake }from"./snowflake.js"; import{ memberjson, presencejson }from"./jsontypes.js"; import{ Dialog }from"./dialog.js"; +import { I18n } from "./i18n.js"; class Member extends SnowFlake{ static already = {}; @@ -213,10 +214,10 @@ class Member extends SnowFlake{ let reason = ""; const menu = new Dialog([ "vdiv", - ["title", "Kick " + this.name + " from " + this.guild.properties.name], + ["title", I18n.getTranslation("member.kick",this.name,this.guild.properties.name)], [ "textbox", - "Reason:", + I18n.getTranslation("member.reason:"), "", function(e: Event){ reason = (e.target as HTMLInputElement).value; @@ -225,7 +226,7 @@ class Member extends SnowFlake{ [ "button", "", - "submit", + I18n.getTranslation("submit"), ()=>{ this.kickAPI(reason); menu.hide(); @@ -246,10 +247,10 @@ class Member extends SnowFlake{ let reason = ""; const menu = new Dialog([ "vdiv", - ["title", "Ban " + this.name + " from " + this.guild.properties.name], + ["title", I18n.getTranslation("member.ban",this.name,this.guild.properties.name)], [ "textbox", - "Reason:", + I18n.getTranslation("member.reason",this.name,this.guild.properties.name), "", function(e: Event){ reason = (e.target as HTMLInputElement).value; @@ -258,7 +259,7 @@ class Member extends SnowFlake{ [ "button", "", - "submit", + I18n.getTranslation("submit",this.name,this.guild.properties.name), ()=>{ this.banAPI(reason); menu.hide(); diff --git a/src/webpage/register.ts b/src/webpage/register.ts index 91fa48a..ac871e5 100644 --- a/src/webpage/register.ts +++ b/src/webpage/register.ts @@ -1,4 +1,6 @@ +import { I18n } from "./i18n.js"; import{ checkInstance, adduser }from"./login.js"; +import { MarkDown } from "./markdown.js"; const registerElement = document.getElementById("register"); if(registerElement){ @@ -18,8 +20,7 @@ async function registertry(e: Event){ const captchaKey = (elements[7] as HTMLInputElement)?.value; if(password !== confirmPassword){ - (document.getElementById("wrong") as HTMLElement).textContent = -"Passwords don't match"; + (document.getElementById("wrong") as HTMLElement).textContent = I18n.getTranslation("localuser.PasswordsNoMatch"); return; } @@ -83,22 +84,22 @@ function handleErrors(errors: any, elements: HTMLFormControlsCollection){ }else if(errors.password){ showError( elements[3] as HTMLElement, -"Password: " + errors.password._errors[0].message +I18n.getTranslation("register.passwordError",errors.password._errors[0].message) ); }else if(errors.username){ showError( elements[2] as HTMLElement, -"Username: " + errors.username._errors[0].message +I18n.getTranslation("register.usernameError",errors.username._errors[0].message) ); }else if(errors.email){ showError( elements[1] as HTMLElement, -"Email: " + errors.email._errors[0].message +I18n.getTranslation("register.emailError",errors.email._errors[0].message) ); }else if(errors.date_of_birth){ showError( elements[5] as HTMLElement, -"Date of Birth: " + errors.date_of_birth._errors[0].message +I18n.getTranslation("register.DOBError",errors.date_of_birth._errors[0].message) ); }else{ (document.getElementById("wrong") as HTMLElement).textContent = @@ -125,8 +126,6 @@ function showError(element: HTMLElement, message: string){ errorElement.textContent = message; } -let TOSa = document.getElementById("TOSa") as HTMLAnchorElement | null; - async function tosLogic(){ const instanceInfo = JSON.parse(localStorage.getItem("instanceinfo") ?? "{}"); const apiurl = new URL(instanceInfo.api); @@ -136,14 +135,12 @@ async function tosLogic(){ const tosPage = data.instance.tosPage; if(tosPage){ -document.getElementById("TOSbox")!.innerHTML = -"I agree to the Terms of Service:"; -TOSa = document.getElementById("TOSa") as HTMLAnchorElement; -TOSa.href = tosPage; + const box=document.getElementById("TOSbox"); + if(!box) return; + box.innerHTML =""; + box.append(new MarkDown(I18n.getTranslation("register.agreeTOS",tosPage)).makeHTML()); }else{ -document.getElementById("TOSbox")!.textContent = -"This instance has no Terms of Service, accept ToS anyways:"; -TOSa = null; + document.getElementById("TOSbox")!.textContent =I18n.getTranslation("register.noTOS"); } console.log(tosPage); } diff --git a/src/webpage/role.ts b/src/webpage/role.ts index b0256dc..d31fb64 100644 --- a/src/webpage/role.ts +++ b/src/webpage/role.ts @@ -142,6 +142,7 @@ class PermissionToggle implements OptionsElement{ import{ OptionsElement, Buttons }from"./settings.js"; import { Contextmenu } from "./contextmenu.js"; import { Channel } from "./channel.js"; +import { I18n } from "./i18n.js"; class RoleList extends Buttons{ permissions: [Role, Permissions][]; permission: Permissions; @@ -204,26 +205,26 @@ class RoleList extends Buttons{ this.redoButtons(); } makeguildmenus(option:Options){ - option.addButtonInput("","Display settings",()=>{ + option.addButtonInput("",I18n.getTranslation("role.displaySettings"),()=>{ const role=this.guild.roleids.get(this.curid as string); if(!role) return; - const form=option.addSubForm("Display settings",()=>{},{ + const form=option.addSubForm(I18n.getTranslation("role.displaySettings"),()=>{},{ fetchURL:this.info.api+"/guilds/"+this.guild.id+"/roles/"+this.curid, method:"PATCH", headers:this.headers, traditionalSubmit:true }); - form.addTextInput("Role Name:","name",{ + form.addTextInput(I18n.getTranslation("role.name"),"name",{ initText:role.name }); - form.addCheckboxInput("Hoisted:","hoist",{ + form.addCheckboxInput(I18n.getTranslation("role.hoisted"),"hoist",{ initState:role.hoist }); - form.addCheckboxInput("Allow anyone to ping this role:","mentionable",{ + form.addCheckboxInput(I18n.getTranslation("role.mentionable"),"mentionable",{ initState:role.mentionable }); const color="#"+role.color.toString(16).padStart(6,"0"); - form.addColorInput("Color","color",{ + form.addColorInput(I18n.getTranslation("role.color"),"color",{ initColor:color }); form.addPreprocessor((obj:any)=>{ @@ -236,7 +237,7 @@ class RoleList extends Buttons{ static guildrolemenu=this.GuildRoleMenu(); private static ChannelRoleMenu(){ const menu=new Contextmenu("role settings"); - menu.addbutton("Remove role",function(role){ + menu.addbutton(()=>I18n.getTranslation("role.remove"),function(role){ if(!this.channel) return; console.log(role); fetch(this.info.api+"/channels/"+this.channel.id+"/permissions/"+role.id,{ @@ -248,8 +249,8 @@ class RoleList extends Buttons{ } private static GuildRoleMenu(){ const menu=new Contextmenu("role settings"); - menu.addbutton("Delete Role",function(role){ - if(!confirm("Are you sure you want to delete "+role.name+"?")) return; + menu.addbutton(()=>I18n.getTranslation("role.delete"),function(role){ + if(!confirm(I18n.getTranslation("role.confirmDelete"))) return; console.log(role); fetch(this.info.api+"/guilds/"+this.guild.id+"/roles/"+role.id,{ method:"DELETE", diff --git a/src/webpage/settings.ts b/src/webpage/settings.ts index 8e7fd73..9c21cf2 100644 --- a/src/webpage/settings.ts +++ b/src/webpage/settings.ts @@ -1,3 +1,5 @@ +import { I18n } from "./i18n.js"; + interface OptionsElement { // generateHTML(): HTMLElement; @@ -828,9 +830,9 @@ class Options implements OptionsElement{ div.classList.add("flexltr", "savediv"); const span = document.createElement("span"); div.append(span); - span.textContent = "Careful, you have unsaved changes"; + span.textContent = I18n.getTranslation("settings.unsaved"); const button = document.createElement("button"); - button.textContent = "Save changes"; + button.textContent = I18n.getTranslation("settings.save"); div.append(button); this.haschanged = true; this.owner.changed(div); @@ -886,7 +888,7 @@ class Form implements OptionsElement{ onSubmit: (arg1: object) => void, { ltr = false, - submitText = "Submit", + submitText = I18n.getTranslation("submit"), fetchURL = "", headers = {}, method = "POST", @@ -919,7 +921,7 @@ class Form implements OptionsElement{ onSubmit: (arg1: object) => void, { ltr = false, - submitText = "Submit", + submitText = I18n.getTranslation("submit"), fetchURL = "", headers = {}, method = "POST", diff --git a/src/webpage/translations/en.json b/src/webpage/translations/en.json index d9e3d8b..bb58f6a 100644 --- a/src/webpage/translations/en.json +++ b/src/webpage/translations/en.json @@ -161,6 +161,19 @@ "uptimeStats":"Uptime: \n All time: $1\nThis week: $2\nToday: $3", "warnOffiline":"Instance is offline, can't connect" }, + "register":{ + "passwordError:":"Password: $1", + "usernameError":"Username: $1", + "emailError":"Email: $1", + "DOBError":"Date of Birth: $1", + "agreeTOS":"I agree to the [Terms of Service]($1):", + "noTOS":"This instance has no Terms of Service, accept ToS anyways:" + }, + "leaving":"You're leaving Spacebar", + "goingToURL":"You're going to $1. Are you sure you want to go there?", + "goThere":"Go there", + "goThereTrust":"Go there and trust in the future", + "nevermind":"Nevermind", "submit":"submit", "guild":{ "copyId":"Copy guild id", @@ -191,7 +204,21 @@ "noDelete":"Nevermind", "create":"Create guild", "loadingDiscovery":"Loading...", - "disoveryTitle":"Guild discovery ($1) {{PLURAL:$1|entrie|entries}}" + "disoveryTitle":"Guild discovery ($1) {{PLURAL:$1|entry|entries}}" + }, + "role":{ + "displaySettings":"Display settings", + "name":"Role name:", + "hoisted":"Hoisted:", + "mentionable":"Allow anyone to ping this role:", + "color":"Color", + "remove":"Remove role", + "delete":"Delete Role", + "confirmDelete":"Are you sure you want to delete $1?" + }, + "settings":{ + "unsaved":"Careful, you have unsaved changes", + "save":"Save changes" }, "localuser":{ "settings":"Settings", @@ -224,7 +251,42 @@ "password:":"Password", "newEmail:":"New email", "changeUsername":"Change username", - "newUsername":"New username:" + "newUsername":"New username:", + "changePassword":"Change password", + "oldPassword:":"Old password:", + "newPassword:":"New password:", + "PasswordsNoMatch":"Password don't match", + "disableConnection":"This connection has been disabled server-side", + "devPortal":"Developer Portal", + "createApp":"Create application", + "team:":"Team:", + "appName":"Application name:", + "description":"Description:", + "privacyPolcyURL":"Privacy policy URL:", + "TOSURL":"Terms of Service URL:", + "publicAvaliable":"Make bot publicly inviteable?", + "requireCode":"Require code grant to invite the bot?", + "manageBot":"Manage bot", + "addBot":"Add bot", + "confirmAddBot":"Are you sure you want to add a bot to this application? There's no going back.", + "confuseNoBot":"For some reason, this application doesn't have a bot (yet).", + "editingBot":"Editing bot $1", + "botUsername":"Bot username:", + "botAvatar":"Bot avatar:", + "resetToken":"Reset Token", + "confirmReset":"Are you sure you want to reset the bot token? Your bot will stop working until you update it.", + "tokenDisplay":"Token: $1", + "saveToken":"Save token to localStorage", + "noToken":"Don't know token so can't save it to localStorage, sorry", + "advancedBot":"Advanced Bot Settings", + "botInviteCreate":"Bot Invite Creator" + }, + "instanceStats":{ + "name":"Instance stats: $1", + "users":"Registered users: $1", + "servers":"Servers: $1", + "messages":"Messages: $1", + "members":"Members: $1" }, "inviteOptions":{ "title":"Invite People", @@ -239,6 +301,7 @@ "limit":"$1 {{PLURAL:$1|use|uses}}", "noLimit":"No limit" }, + "2faCode":"2FA code:", "invite":{ "invitedBy":"You've been invited by $1", "alreadyJoined":"Already joined", @@ -258,7 +321,26 @@ "user":{ "copyId":"Copy user ID", "online":"Online", - "offline":"Offline" + "offline":"Offline", + "message":"Message user", + "block":"Block user", + "unblock":"unblock user", + "friendReq":"Friend request", + "kick":"Kick member", + "ban":"Ban member", + "addRole":"Add roles", + "removeRole":"Remove roles" + }, + "login":{ + "checking":"Checking Instance", + "allGood":"All good", + "invalid":"Invalid Instance, try again", + "waiting":"Waiting to check Instance" + }, + "member":{ + "kick":"Kick $1 from $2", + "reason:":"Reason:", + "ban":"Ban $1 from $2" }, "errorReconnect":"Unable to connect to the server, retrying in $1 seconds...", "retrying":"Retrying...", diff --git a/src/webpage/user.ts b/src/webpage/user.ts index dd0f5a8..5723b86 100644 --- a/src/webpage/user.ts +++ b/src/webpage/user.ts @@ -7,6 +7,7 @@ import{ SnowFlake }from"./snowflake.js"; import{ presencejson, userjson }from"./jsontypes.js"; import { Role } from "./role.js"; import { Search } from "./search.js"; +import { I18n } from "./i18n.js"; class User extends SnowFlake{ owner: Localuser; @@ -96,10 +97,10 @@ class User extends SnowFlake{ static contextmenu = new Contextmenu("User Menu"); static setUpContextMenu(): void{ - this.contextmenu.addbutton("Copy user id", function(this: User){ + this.contextmenu.addbutton(()=>I18n.getTranslation("user.copyId"), function(this: User){ navigator.clipboard.writeText(this.id); }); - this.contextmenu.addbutton("Message user", function(this: User){ + this.contextmenu.addbutton(()=>I18n.getTranslation("user.message"), function(this: User){ fetch(this.info.api + "/users/@me/channels", { method: "POST", body: JSON.stringify({ recipients: [this.id] }), @@ -111,7 +112,7 @@ class User extends SnowFlake{ }); }); this.contextmenu.addbutton( - "Block user", + ()=>I18n.getTranslation("user.block"), function(this: User){ this.block(); }, @@ -122,7 +123,7 @@ class User extends SnowFlake{ ); this.contextmenu.addbutton( - "Unblock user", + ()=>I18n.getTranslation("user.unblock"), function(this: User){ this.unblock(); }, @@ -131,7 +132,7 @@ class User extends SnowFlake{ return this.relationshipType === 2; } ); - this.contextmenu.addbutton("Friend request", function(this: User){ + this.contextmenu.addbutton(()=>I18n.getTranslation("user.friendReq"), function(this: User){ fetch(`${this.info.api}/users/@me/relationships/${this.id}`, { method: "PUT", headers: this.owner.headers, @@ -141,7 +142,7 @@ class User extends SnowFlake{ }); }); this.contextmenu.addbutton( - "Kick member", + ()=>I18n.getTranslation("user.kick"), function(this: User, member: Member | undefined){ member?.kick(); }, @@ -159,7 +160,7 @@ class User extends SnowFlake{ } ); this.contextmenu.addbutton( - "Ban member", + ()=>I18n.getTranslation("user.ban"), function(this: User, member: Member | undefined){ member?.ban(); }, @@ -177,7 +178,7 @@ class User extends SnowFlake{ } ); this.contextmenu.addbutton( - "Add roles", + ()=>I18n.getTranslation("user.addRole"), async function(this: User, member: Member | undefined,e){ if(member){ e.stopPropagation(); @@ -203,7 +204,7 @@ class User extends SnowFlake{ } ); this.contextmenu.addbutton( - "Remove roles", + ()=>I18n.getTranslation("user.removeRole"), async function(this: User, member: Member | undefined,e){ if(member){ e.stopPropagation();