From f2243859cf56573c6dc2e56325efe9eb9b7574b8 Mon Sep 17 00:00:00 2001 From: "puya.bahrani" Date: Fri, 29 Nov 2024 21:12:17 +0100 Subject: [PATCH 01/16] italian translation --- src/gui/src/i18n/translations/it.js | 30 ++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/gui/src/i18n/translations/it.js b/src/gui/src/i18n/translations/it.js index 8d1720fd6..f50f68780 100644 --- a/src/gui/src/i18n/translations/it.js +++ b/src/gui/src/i18n/translations/it.js @@ -349,21 +349,21 @@ const it = { // *********************************** // Missing translations // *********************************** - "change": undefined, // In English: "Change" - "clock_visibility": undefined, // In English: "Clock Visibility" - "reading": undefined, // In English: "Reading %strong%" - "writing": undefined, // In English: "Writing %strong%" - "unzipping": undefined, // In English: "Unzipping %strong%" - "sequencing": undefined, // In English: "Sequencing %strong%" - "zipping": undefined, // In English: "Zipping %strong%" - "Editor": undefined, // In English: "Editor" - "Viewer": undefined, // In English: "Viewer" - "People with access": undefined, // In English: "People with access" - "Share With…": undefined, // In English: "Share With…" - "Owner": undefined, // In English: "Owner" - "You can't share with yourself.": undefined, // In English: "You can't share with yourself." - "This user already has access to this item": undefined, // In English: "This user already has access to this item" + change: 'Cambia', // In English: "Change" + clock_visibility: 'Visibilità dell`ora', // In English: "Clock Visibility" + reading: 'Lettura %strong%', // In English: "Reading %strong%" + writing: 'Scrittura %strong%', // In English: "Writing %strong%" + unzipping: 'Unzip %strong%', // In English: "Unzipping %strong%" + sequencing: 'Ordinamento', // In English: "Sequencing %strong%" + zipping: 'Zipping %strong%', // In English: "Zipping %strong%" + Editor: 'Editor', // In English: "Editor" + Viewer: 'Visualizzatore', // In English: "Viewer" + "People with access": 'Persone con accesso', // In English: "People with access" + "Share With…": 'Condividi con…', // In English: "Share With…" + Owner: 'Proprietario', // In English: "Owner" + "You can't share with yourself.": 'Non puoi condividere con te stesso', // In English: "You can't share with yourself." + "This user already has access to this item": 'L`utente ha già effettuato l`accesso a questo elemento', // In English: "This user already has access to this item" } }; -export default it; +export default it; \ No newline at end of file From 9f726b3e75d46169071d8c40bc225eb7ef692668 Mon Sep 17 00:00:00 2001 From: KernelDeimos Date: Fri, 29 Nov 2024 15:22:16 -0500 Subject: [PATCH 02/16] dev: add ai comment generator --- tools/comment-writer/config.json | 4 + tools/comment-writer/main.js | 592 ++++++++++++++++++++++++++++++ tools/comment-writer/package.json | 22 ++ 3 files changed, 618 insertions(+) create mode 100644 tools/comment-writer/config.json create mode 100644 tools/comment-writer/main.js create mode 100644 tools/comment-writer/package.json diff --git a/tools/comment-writer/config.json b/tools/comment-writer/config.json new file mode 100644 index 000000000..882ad6644 --- /dev/null +++ b/tools/comment-writer/config.json @@ -0,0 +1,4 @@ +{ + "api_url": "https://api.puter.local", + "auth_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0IjoicyIsInYiOiIwLjAuMCIsInUiOiJoenFEOSsvYVFpZW9HbmdWc1laMFZRPT0iLCJ1dSI6Ii90RFFPU0dJU3lxMU9TSmg5ZThic2c9PSIsImlhdCI6MTczMjg4OTIwNn0.i4s3H2jvkvPKVW-ji83Gn8nUFBH7NIB4NsprEDgU89Y" +} diff --git a/tools/comment-writer/main.js b/tools/comment-writer/main.js new file mode 100644 index 000000000..bf79364e2 --- /dev/null +++ b/tools/comment-writer/main.js @@ -0,0 +1,592 @@ +const enq = require('enquirer'); +const wrap = require('word-wrap'); +const dedent = require('dedent'); +const axios = require('axios'); + +const { walk, EXCLUDE_LISTS } = require('../file-walker/test'); + +const https = require('https'); +const fs = require('fs'); +const path_ = require('path'); + +const FILE_EXCLUDES = [ + /^\.git/, + /^node_modules\//, + /\/node_modules$/, + /^node_modules$/, + /package-lock\.json/, + /^src\/dev-center\/js/, + /src\/backend\/src\/public\/assets/, + /^src\/gui\/src\/lib/, + /^eslint\.config\.js$/, +]; + +const axi = axios.create({ + httpsAgent: new https.Agent({ + rejectUnauthorized: false + }) +}); + +const cwd = process.cwd(); +const context = {}; + +context.config = JSON.parse( + fs.readFileSync('config.json') +); + +class AI { + constructor (context) { + // + } + + async complete ({ messages }) { + const response = await axi.post(`${context.config.api_url}/drivers/call`, { + interface: 'puter-chat-completion', + method: 'complete', + args: { + messages, + }, + }, { + headers: { + "Content-Type": "application/json", + Origin: 'https://puter.local', + Authorization: `Bearer ${context.config.auth_token}`, + }, + }); + + return response.data.result.message; + } +} + +class CommentWriter { + // +} + +class JavascriptFileProcessor { + constructor (context, parameters) { + this.context = context; + this.parameters = parameters; + } + + process (lines) { + const definitions = []; + for ( let i = 0 ; i < lines.length ; i++ ) { + const line = lines[i]; + for ( const matcher of this.parameters.definition_matchers ) { + const match = matcher.pattern.exec(line); + console.log('match object', match); + + if ( match ) { + definitions.push({ + ...matcher.handler(match), + line: i, + }); + break; + } + } + } + return { definitions }; + } +} + +const js_processor = new JavascriptFileProcessor(context, { + definition_matchers: [ + // { + // name: 'require', + // pattern: /const (\w+) = require\(['"](.+)['"]\);/, + // handler: (match) => { + // const [ , name, path ] = match; + // return { + // type: 'require', + // name, + // path, + // }; + // } + // }, + { + name: 'class', + pattern: /class (\w+)(?: extends (.+))? {/, + handler: (match) => { + const [ , name, parent ] = match; + return { + type: 'class', + name, + parent, + }; + } + }, + { + name: 'method', + pattern: /^\s*async .*\(.*\).*{/, + handler: (match) => { + const [ , name ] = match; + return { + async: true, + type: 'method', + name, + }; + } + }, + { + name: 'method', + pattern: /^\s*[A-Za-z_\$]+.*\(\).*{/, + handler: (match) => { + const [ , name ] = match; + return { + type: 'method', + name, + }; + } + }, + { + name: 'function', + pattern: /^\s*function .*\(.*\).*{/, + handler: (match) => { + const [ , name ] = match; + return { + type: 'function', + scope: 'function', + name, + }; + } + }, + { + name: 'function', + pattern: /const [A-Za-z_]+\s*=\s*\(.*\)\s*=>\s*{/, + handler: (match) => { + const [ , name, args ] = match; + return { + type: 'function', + scope: 'lexical', + name, + args: args.split(',').map(arg => arg.trim()), + }; + } + }, + { + name: 'const', + // pattern to match only uppercase-lettered variable names + pattern: /const ([A-Z_]+) = (.+);/, + handler: (match) => { + const [ , name, value ] = match; + return { + type: 'const', + name, + value, + }; + } + } + ], +}); + +const create_limited_view = (lines, key_places) => { + // Sort key places by starting line + key_places.sort((a, b) => { + const a_start = Math.max(0, a.anchor - a.lines_above); + const b_start = Math.max(0, b.anchor - b.lines_above); + return a_start - b_start; + }); + + const visible_ranges = []; + + // Create visible ranges for each key place + for ( const key_place of key_places ) { + const anchor = key_place.anchor; + const lines_above = key_place.lines_above; + const lines_below = key_place.lines_below; + + const start = Math.max(0, anchor - lines_above); + const end = Math.min(lines.length, anchor + lines_below); + + visible_ranges.push({ + anchor: key_place.anchor, + comment: key_place.comment, + start, + end, + }); + } + + // Merge overlapping visible ranges + const merged_ranges = []; + + for ( const range of visible_ranges ) { + range.comments = [{ + anchor: range.anchor, + text: range.comment + }]; + + if ( ! merged_ranges.length ) { + merged_ranges.push(range); + continue; + } + + const last_range = merged_ranges[merged_ranges.length - 1]; + + if ( last_range.end >= range.start ) { + last_range.end = Math.max(last_range.end, range.end); + last_range.comments.push({ + anchor: range.anchor, + text: range.comment + }); + } else { + merged_ranges.push(range); + } + } + + // Create the limited view, adding line numbers and comments + let limited_view = ''; + + let previous_visible_range = null; + for ( let i = 0 ; i < lines.length ; i++ ) { + const line = lines[i]; + + let visible_range = null; + + if ( i === 22 ) debugger; + + for ( const range of merged_ranges ) { + if ( i >= range.start && i < range.end ) { + visible_range = range; + break; + } + } + + // console.log('visible_range', visible_range, i); + + if ( visible_range === null ) { + continue; + } + + if ( visible_range !== previous_visible_range ) { + if ( i !== 0 ) limited_view += '\n'; + if ( visible_range.comments.length === 1 ) { + const comment = visible_range.comments[0]; + limited_view += `window around line ${comment.anchor}: ${comment.text}\n`; + } else { + limited_view += `window around lines ${visible_range.comments.length} key lines:\n`; + for ( const comment of visible_range.comments ) { + limited_view += `- line ${comment.anchor}: ${comment.text}\n`; + } + } + } + + previous_visible_range = visible_range; + + limited_view += `${i + 1}: ${line}\n`; + } + + return limited_view; +}; + +/** + * Inject comments into lines + * @param {*} lines - Array of original file lines + * @param {*} comments - Array of comment objects + * + * Comment object structure: + * { + * position: 0, // Position in lines array + * lines: [ 'comment line 1', 'comment line 2', ... ] + * } + */ +const inject_comments = (lines, comments) => { + // Sort comments in reverse order + comments.sort((a, b) => b.position - a.position); + + // Inject comments into lines + for ( const comment of comments ) { + // AI might have been stupid and added a comment above a blank line, + // despite that we told it not to do that. So we need to adjust the position. + while ( comment.position < lines.length && ! lines[comment.position].trim() ) { + comment.position++; + } + + const indentation = lines[comment.position].match(/^\s*/)[0]; + console.log('????', comment.position, lines[comment.position], '|' + indentation + '|'); + const comment_lines = comment.lines.map(line => `${indentation}${line}`); + lines.splice(comment.position, 0, ...comment_lines); + } +} + +const textutil = {}; +textutil.format = text => { + return wrap(dedent(text), { + width: 80, + indent: '| ' + }); +}; + +context.ai = new AI(context); + +const main = async () => { + // const message = await context.ai.complete({ + // messages: [ + // { + // role: 'user', + // content: ` + // Introduce yourself as the Puter Comment Writer. You are an AI that will + // write comments in code files. A file walker will be used to iterate over + // the source files and present them one at a time, and the user will accept, + // reject, or request edits interactively. For each new file, a clean AI + // context will be created. + // `.trim() + // } + // ] + // }); + // const intro = message.content; + const intro = textutil.format(` + Hello! I am the Puter Comment Writer, an AI designed to enhance your code files with meaningful comments. As you walk through your source files, I will provide insights, explanations, and clarifications tailored to the specific content of each file. You can choose to accept my comments, request edits for more clarity or detail, or even reject them if they don't meet your needs. Each time we move to a new file, I'll start fresh with a clean context, ready to help you improve your code documentation. Let's get started! + `); + console.log(intro); + + console.log(`Enter a path relative to: ${process.cwd()}`); + console.log('arg?', process.argv[2]); + let rootpath = process.argv[2] ? { path: process.argv[2] } : await enq.prompt({ + type: 'input', + name: 'path', + message: 'Enter path:' + }); + + rootpath = path_.resolve(rootpath.path); + console.log('rootpath:', rootpath); + + const walk_iter = walk({ + excludes: FILE_EXCLUDES, + }, rootpath); + + for await ( const value of walk_iter ) { + if ( value.is_dir ) { + console.log('directory:', value.path); + continue; + } + if ( ! value.name.endsWith('.js') ) { + continue; + } + console.log('file:', value.path); + const lines = fs.readFileSync(value.path, 'utf8').split('\n'); + + if ( lines[0].startsWith('// METADATA // ') ) { + const metadata = JSON.parse(lines[0].slice('// METADATA // '.length)); + if ( metadata['ai-commented'] ) { + console.log('File was already commented by AI; skipping...'); + continue; + } + } + + const action = await enq.prompt({ + type: 'select', + name: 'action', + message: 'Select action:', + choices: [ + 'generate', + 'skip', + 'exit', + ] + }) + + if ( action.action === 'exit' ) { + break; + } + + if ( action.action === 'skip' ) { + continue; + } + + const { definitions } = js_processor.process(lines); + const key_places = []; + key_places.push({ + anchor: 0, + lines_above: 2, + lines_below: 200, + comment: `Top of file: ${value.path}` + }); + key_places.push({ + anchor: lines.length - 1, + lines_above: 200, + lines_below: 2, + comment: `Bottom of ${value.name}` + }); + for ( const definition of definitions ) { + key_places.push({ + anchor: definition.line, + lines_above: 40, + lines_below: 40, + comment: `${definition.type}.` + }); + } + let limited_view = create_limited_view(lines, key_places); + console.log('--- view ---'); + console.log(limited_view); + + const comments = []; + // comments.push({ + // position: 0, + // }); + // for ( const definition of definitions ) { + // comments.push({ + // position: definition.line, + // definition, + // }); + // } + + // This was worth a try but the LLM is very bad at this + /* + const message = await context.ai.complete({ + messages: [ + { + role: 'user', + content: dedent(` + Respond with comma-separated numbers only, with no surrounding text. + Please write the numbers of the lines above which a comment should be added. + Do not include numbers of lines that are blank, already have comments, or are part of a comment. + Prefer comment locations in a higher level scope, such as a classes, function definitions and class methods, + `).trim() + '\n\n' + limited_view + } + ] + }); + const numbers = message.content.split(',').map(n => Number(n)); + + for ( const n of numbers ) { + if ( Number.isNaN(n) ) { + console.log('Invalid number:', n); + continue; + } + + comments.push({ + position: n - 1, + }); + } + */ + + for ( const def of definitions ) { + console.log('def?', def); + let instruction = ''; + + if ( def.type === 'class' ) { + instruction = dedent(` + Since the comment is going above a class definition, please write a JSDoc style comment. + Make the comment as descriptive as possible, including the class name and its purpose. + `); + } + + if ( def.type === 'method' ) { + instruction = dedent(` + Since the comment is going above a method, please write a JSDoc style comment. + The comment should include a short concise description of the method's purpose, + notes about its behavior, and any parameters or return values. + `); + } + + if ( def.type === 'const' ) { + instruction = dedent(` + Since the comment is going above a constant definition, please write a comment that explains + the purpose of the constant and how it is used in the code. + The comment should be only one or two lines long, and should use line comments. + `); + } + + comments.push({ + position: def.line, + instruction: instruction, + }); + } + + for ( const comment of comments ) { + // This doesn't work very well yet + /* + const ranges_message = await context.ai.complete({ + messages: [ + { + role: 'user', + content: dedent(` + Please only respond with comma-separated number ranges in this format with no surrounding text: + 11-21, 25-30, 35-40 + + You may also respond with "none". + + A comment will be added above line ${comment.position} in the code which follows. + You are seeing a limited view of the code that includes chunks around interesting lines. + Please specify ranges of lines that might provide useful context for this comment. + Do not include in any range lines which are already visible in the limited view. + Avoid specifying more than a couple hundred lines. + `).trim() + '\n\n' + limited_view + } + ] + }); + + if ( ranges_message.content.trim() !== 'none' ) { + const ranges = ranges_message.content.split(',').map(range => { + const [ start, end ] = range.split('-').map(n => Number(n)); + return { start, end }; + }); + + for ( const range of ranges ) { + key_places.push({ + anchor: range.start, + lines_above: 0, + lines_below: range.end - range.start, + comment: `Requested range by AI agent: ${range.start}-${range.end}` + }); + } + + limited_view = create_limited_view(lines, key_places); + console.log('--- updated view ---'); + console.log(limited_view); + } + */ + + const message = await context.ai.complete({ + messages: [ + { + role: 'user', + content: dedent(` + Please write a comment to be added above line ${comment.position}. + Do not write any surrounding text; just the comment itself. + Please include comment markers. If the comment is on a class, function, or method, please use jsdoc style. + The code is written in JavaScript. + `).trim() + + (comment.instruction ? '\n\n' + dedent(comment.instruction) : '') + + '\n\n' + limited_view + } + ] + }); + console.log('message:', message); + comment.lines = message.content.split('\n'); + + // Remove leading and trailing blank lines + while ( comment.lines.length && ! comment.lines[0].trim() ) { + comment.lines.shift(); + } + while ( comment.lines.length && ! comment.lines[comment.lines.length - 1].trim() ) { + comment.lines.pop(); + } + + // Remove leading "```" or "```" lines + if ( comment.lines[0].startsWith('```') ) { + comment.lines.shift(); + } + + // Remove trailing "```" lines + if ( comment.lines[comment.lines.length - 1].startsWith('```') ) { + comment.lines.pop(); + } + + comment.lines = dedent(comment.lines.join('\n')).split('\n'); + } + + inject_comments(lines, comments); + + console.log('--- lines ---'); + console.log(lines); + + lines.unshift('// METADATA // ' + JSON.stringify({ + 'ai-commented': true, + })); + + // Write the modified file + fs.writeFileSync(value.path, lines.join('\n')); + } + +}; + +main(); diff --git a/tools/comment-writer/package.json b/tools/comment-writer/package.json new file mode 100644 index 000000000..8b3eb7937 --- /dev/null +++ b/tools/comment-writer/package.json @@ -0,0 +1,22 @@ +{ + "name": "comment-writer", + "version": "1.0.0", + "main": "main.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [], + "author": "", + "license": "AGPL-3.0-only", + "description": "", + "dependencies": { + "axios": "^1.7.8", + "console-table-printer": "^2.12.1", + "dedent": "^1.5.3", + "diff-match-patch": "^1.0.5", + "enquirer": "^2.4.1", + "js-levenshtein": "^1.1.6", + "word-wrap": "^1.2.5", + "yaml": "^2.4.5" + } +} From cb70bb2b62593b6d2665411ea49b74d1657ab0cd Mon Sep 17 00:00:00 2001 From: "Daniel, Petrica Andrei-Daniel" Date: Fri, 29 Nov 2024 21:28:56 +0100 Subject: [PATCH 03/16] Update it.js --- src/gui/src/i18n/translations/it.js | 64 ++++++++++++++--------------- 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/src/gui/src/i18n/translations/it.js b/src/gui/src/i18n/translations/it.js index 8d1720fd6..68dbda6c0 100644 --- a/src/gui/src/i18n/translations/it.js +++ b/src/gui/src/i18n/translations/it.js @@ -22,9 +22,9 @@ const it = { english_name: "Italian", code: "it", dictionary: { - about: "About", + about: "Informazioni", // This is better inn the context of the setting page title. It may be tricky. account: "Account", - account_password: "Verifica Account Password", + account_password: "Verifica Password del account", access_granted_to: "Accesso garantito a", add_existing_account: "Aggiungi un account esistente", all_fields_required: "Tutti i campi sono richiesti.", @@ -65,7 +65,7 @@ const it = { confirm_delete_single_item: 'Vuoi eliminare definitivamente questo elemento?', confirm_open_apps_log_out: 'Ci sono delle applicazioni aperte. Sei sicuro di voler effettuare il log out?', confirm_new_password: "Conferma la nuova Password", - confirm_delete_user: "Sei sicuro di voler cancellare il tuo account? tutti i tuoi file e dati saranno definitivamente cancellati. Quest'azione non è reversibile.", + confirm_delete_user: "Sei sicuro di voler cancellare il tuo account? Tutti i tuoi file e dati saranno definitivamente cancellati. Quest'azione non è reversibile.", confirm_delete_user_title: "Cancellare l'Account?", confirm_session_revoke: "Sei sicuro di voler revocare questa sessione?", confirm_your_email_address: "Conferma il tuo indirizzo email", @@ -81,31 +81,31 @@ const it = { create_account: "Crea Account", create_free_account: "Crea un account gratis", create_shortcut: "Crea Scorciatoia", - credits: "Credits", - current_password: "Password corrente", + credits: "Crediti", + current_password: "Password attuale", cut: 'Taglia', clock: "Orologio", clock_visible_hide: 'Nascondi - Sempre nascosto', clock_visible_show: 'Mostra - Sempre visibile', clock_visible_auto: 'Auto - Default, visibile solo in modalità schermo intero', - close_all: 'Close All', - created: 'Created', + close_all: 'Chiudi tutte', + created: 'Creata', date_modified: 'Data ultima modifica', - default: 'Default', + default: 'Predefinita', delete: 'Elimina', delete_account: "Elimina Account", delete_permanently: "Elimina permanentemente", deleting_file: "Eliminando %%", deploy_as_app: 'Distribuisci come Applicazione', descending: 'Discendente', - desktop: 'Desktop', + desktop: 'Scrivania', desktop_background_fit: "Adatta", developers: "Sviluppatori", dir_published_as_website: `%strong% è stato pubblicato su:`, disable_2fa: 'Disabilita 2FA', disable_2fa_confirm: "Sei sicuro di voler disabilitare la 2FA?", disable_2fa_instructions: "Inserisci la tua password per disabilitare la 2FA.", - disassociate_dir: "Dissocia la Directory", + disassociate_dir: "Dissocia la Directory", documents: 'Documenti', dont_allow: 'Non consentire', download: 'Scarica', @@ -162,9 +162,9 @@ const it = { looks_good: "Sembra buono!", manage_sessions: "Gestisci le sessioni", menubar_style: "Stile della barra dei menu", - menubar_style_desktop: "Desktop", - menubar_style_system: "System", - menubar_style_window: "Window", + menubar_style_desktop: "Scrivania", + menubar_style_system: "Sistema", + menubar_style_window: "Finestra", modified: 'Modificato', move: 'Sposta', moving_file: "Spostamento in corso %%", @@ -208,7 +208,7 @@ const it = { picture: "Immagine", pictures: 'Immagini', plural_suffix: 'i', - powered_by_puter_js: `Powered by {{link=docs}}Puter.js{{/link}}`, + powered_by_puter_js: `Realizzato con {{link=docs}}Puter.js{{/link}}`, preparing: "Preparazione in corso...", preparing_for_upload: "Preparazione per l’upload...", print: 'Stampa', @@ -218,7 +218,7 @@ const it = { process_status_initializing: "Inizializzando", process_status_running: "In esecuzione", process_type_app: 'App', - process_type_init: 'Init', + process_type_init: 'Inizializzazione', process_type_ui: 'UI', properties: "Proprietà", public: "Pubblico", @@ -254,7 +254,7 @@ const it = { scan_qr_generic: 'Scansiona il codice QR usando il tuo smartphone', search: 'Search', seconds: 'seconds', - security: "Security", + security: "Sicurezza", select: "Seleziona", selected: 'Selezionato', select_color: 'Seleziona un colore…', @@ -314,8 +314,8 @@ const it = { yes: 'Sì', yes_release_it: 'Si, rilascialo', you_have_been_referred_to_puter_by_a_friend: "Sei stato invitato su Puter da un amico!", - zip: "Zip", - zipping_file: "Zipping %strong%", + zip: "File compresso", + zipping_file: "Compressione di %strong%" // === 2FA Setup === setup2fa_1_step_heading: 'Apri la tua app di autenticazione', @@ -349,20 +349,20 @@ const it = { // *********************************** // Missing translations // *********************************** - "change": undefined, // In English: "Change" - "clock_visibility": undefined, // In English: "Clock Visibility" - "reading": undefined, // In English: "Reading %strong%" - "writing": undefined, // In English: "Writing %strong%" - "unzipping": undefined, // In English: "Unzipping %strong%" - "sequencing": undefined, // In English: "Sequencing %strong%" - "zipping": undefined, // In English: "Zipping %strong%" - "Editor": undefined, // In English: "Editor" - "Viewer": undefined, // In English: "Viewer" - "People with access": undefined, // In English: "People with access" - "Share With…": undefined, // In English: "Share With…" - "Owner": undefined, // In English: "Owner" - "You can't share with yourself.": undefined, // In English: "You can't share with yourself." - "This user already has access to this item": undefined, // In English: "This user already has access to this item" + "change": 'Cambia', // In English: "Change" + "clock_visibility": 'Visibilità orologio', // In English: "Clock Visibility" + "reading": 'Legendo %strong%', // In English: "Reading %strong%" + "writing": 'Scrivendo %strong%', // In English: "Writing %strong%" + "unzipping": 'Decompressione di %strong%', // In English: "Unzipping %strong%" + "sequencing": 'Sequenziamento di %strong%', // In English: "Sequencing %strong%" + "zipping": 'Compressione di %strong%', // In English: "Zipping %strong%" + "Editor": 'Editore', // In English: "Editor" + "Viewer": 'Visualizatore', // In English: "Viewer" + "People with access": 'Persone con accesso', // In English: "People with access" + "Share With…": 'Condividi con…', // In English: "Share With…" + "Owner": 'Proprietario', // In English: "Owner" + "You can't share with yourself.": "Non puoi condividere con te stesso", // In English: "You can't share with yourself." + "This user already has access to this item": "Questo utente ha già accesso a questo file", // In English: "This user already has access to this item" } }; From 60e87bdf92c9f4596bd4a675b7985db9b4aff9f4 Mon Sep 17 00:00:00 2001 From: mkalevo <47644570+mkalevo@users.noreply.github.com> Date: Fri, 29 Nov 2024 20:44:56 +0000 Subject: [PATCH 04/16] #871 added missing Finnish translations in fi.js --- src/gui/src/i18n/translations/fi.js | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/gui/src/i18n/translations/fi.js b/src/gui/src/i18n/translations/fi.js index 789ac2a9a..d55d930b9 100644 --- a/src/gui/src/i18n/translations/fi.js +++ b/src/gui/src/i18n/translations/fi.js @@ -407,20 +407,20 @@ const fi = { // *********************************** // Missing translations // *********************************** - "change": undefined, // In English: "Change" - "clock_visibility": undefined, // In English: "Clock Visibility" - "reading": undefined, // In English: "Reading %strong%" - "writing": undefined, // In English: "Writing %strong%" - "unzipping": undefined, // In English: "Unzipping %strong%" - "sequencing": undefined, // In English: "Sequencing %strong%" - "zipping": undefined, // In English: "Zipping %strong%" - "Editor": undefined, // In English: "Editor" - "Viewer": undefined, // In English: "Viewer" - "People with access": undefined, // In English: "People with access" - "Share With…": undefined, // In English: "Share With…" - "Owner": undefined, // In English: "Owner" - "You can't share with yourself.": undefined, // In English: "You can't share with yourself." - "This user already has access to this item": undefined, // In English: "This user already has access to this item" + "change": "Muuta", // In English: "Change" + "clock_visibility": "Kellon näkyvyys", // In English: "Clock Visibility" + "reading": "Luetaan %strong%", // In English: "Reading %strong%" + "writing": "Kirjoitetaan %strong%", // In English: "Writing %strong%" + "unzipping": "Puretaan %strong%", // In English: "Unzipping %strong%" + "sequencing": "Järjestetään %strong%", // In English: "Sequencing %strong%" + "zipping": "Paketoidaan %strong%", // In English: "Zipping %strong%" + "Editor": "Muokkaaja", // In English: "Editor" + "Viewer": "Katsoja", // In English: "Viewer" + "People with access": "Henkilöt, joilla on oikeudet", // In English: "People with access" + "Share With…": "Jaa...", // In English: "Share With…" + "Owner": "Omistaja", // In English: "Owner" + "You can't share with yourself.": "Et voi jakaa itsellesi.", // In English: "You can't share with yourself." + "This user already has access to this item": "Käyttäjällä on jo oikeudet tähän kohteeseen.", // In English: "This user already has access to this item" } } From 8c0c31cd098f37eef9cdc40147898b3dadd74416 Mon Sep 17 00:00:00 2001 From: "Daniel, Petrica Andrei-Daniel" Date: Fri, 29 Nov 2024 22:35:38 +0100 Subject: [PATCH 05/16] Update it.js --- src/gui/src/i18n/translations/it.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/src/i18n/translations/it.js b/src/gui/src/i18n/translations/it.js index 68dbda6c0..1f86159ea 100644 --- a/src/gui/src/i18n/translations/it.js +++ b/src/gui/src/i18n/translations/it.js @@ -22,7 +22,7 @@ const it = { english_name: "Italian", code: "it", dictionary: { - about: "Informazioni", // This is better inn the context of the setting page title. It may be tricky. + about: "Informazioni", // This is better in the context of the setting page title. It may be tricky. account: "Account", account_password: "Verifica Password del account", access_granted_to: "Accesso garantito a", From c97d64da91b74102dc9f8e72b440dcb56dbff517 Mon Sep 17 00:00:00 2001 From: Nariman Jelveh Date: Fri, 29 Nov 2024 13:47:10 -0800 Subject: [PATCH 06/16] Update fi.js --- src/gui/src/i18n/translations/fi.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/gui/src/i18n/translations/fi.js b/src/gui/src/i18n/translations/fi.js index d55d930b9..e3001bc8d 100644 --- a/src/gui/src/i18n/translations/fi.js +++ b/src/gui/src/i18n/translations/fi.js @@ -404,9 +404,6 @@ const fi = { login2fa_recovery_back: 'Takaisin', login2fa_recovery_placeholder: 'XXXXXXXX', - // *********************************** - // Missing translations - // *********************************** "change": "Muuta", // In English: "Change" "clock_visibility": "Kellon näkyvyys", // In English: "Clock Visibility" "reading": "Luetaan %strong%", // In English: "Reading %strong%" @@ -424,4 +421,4 @@ const fi = { } } -export default fi; \ No newline at end of file +export default fi; From 9b74a2e177effe7b4d7a798475e6dec82acbe880 Mon Sep 17 00:00:00 2001 From: jelveh Date: Fri, 29 Nov 2024 14:22:56 -0800 Subject: [PATCH 07/16] Update it.js --- src/gui/src/i18n/translations/it.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/src/i18n/translations/it.js b/src/gui/src/i18n/translations/it.js index cd4641f11..e4842af12 100644 --- a/src/gui/src/i18n/translations/it.js +++ b/src/gui/src/i18n/translations/it.js @@ -315,7 +315,7 @@ const it = { yes_release_it: 'Si, rilascialo', you_have_been_referred_to_puter_by_a_friend: "Sei stato invitato su Puter da un amico!", zip: "File compresso", - zipping_file: "Compressione di %strong%" + zipping_file: "Compressione di %strong%", // === 2FA Setup === setup2fa_1_step_heading: 'Apri la tua app di autenticazione', From e9ba0833daa50d58f7078264c47401feddb11a72 Mon Sep 17 00:00:00 2001 From: Ali Hassan Date: Sat, 30 Nov 2024 00:34:06 +0200 Subject: [PATCH 08/16] Review Undefined Words and Correct it --- src/gui/src/i18n/translations/fi.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/gui/src/i18n/translations/fi.js b/src/gui/src/i18n/translations/fi.js index e3001bc8d..c9d0d4e81 100644 --- a/src/gui/src/i18n/translations/fi.js +++ b/src/gui/src/i18n/translations/fi.js @@ -354,6 +354,8 @@ const fi = { // "Type of an object" => 'Tyyppi' or // "Type on the keyboard" => 'Kirjoita' + + type_confirm_to_delete_account: "Kirjoita 'vahvista' poistaaksesi tilisi.", ui_colors: "Käyttöliittymän värit", ui_manage_sessions: "Istunnon hallinta", @@ -395,6 +397,7 @@ const fi = { setup2fa_5_confirmation_2: 'Olen valmis ottamaan kaksivaiheisen tunnistautumisen käyttöön', setup2fa_5_button: 'Ota kaksivaiheinen tunnistautuminen käyttöön', + // === 2FA Login === login2fa_otp_title: 'Syötä kaksivaiheisen tunnistautumisen koodi', login2fa_otp_instructions: 'Syötä kuusinumeroinen koodi todennussovelluksestasi.', @@ -404,7 +407,9 @@ const fi = { login2fa_recovery_back: 'Takaisin', login2fa_recovery_placeholder: 'XXXXXXXX', - "change": "Muuta", // In English: "Change" + + + "change": "Muuta", // In English: "Change" "clock_visibility": "Kellon näkyvyys", // In English: "Clock Visibility" "reading": "Luetaan %strong%", // In English: "Reading %strong%" "writing": "Kirjoitetaan %strong%", // In English: "Writing %strong%" @@ -414,11 +419,10 @@ const fi = { "Editor": "Muokkaaja", // In English: "Editor" "Viewer": "Katsoja", // In English: "Viewer" "People with access": "Henkilöt, joilla on oikeudet", // In English: "People with access" - "Share With…": "Jaa...", // In English: "Share With…" + "Share With…": "Jaa kanssa…", // In English: "Share With…" "Owner": "Omistaja", // In English: "Owner" "You can't share with yourself.": "Et voi jakaa itsellesi.", // In English: "You can't share with yourself." "This user already has access to this item": "Käyttäjällä on jo oikeudet tähän kohteeseen.", // In English: "This user already has access to this item" } } - export default fi; From e662c782b745f4f98024d1353a6a162d5fe58c44 Mon Sep 17 00:00:00 2001 From: jelveh Date: Fri, 29 Nov 2024 19:26:13 -0800 Subject: [PATCH 09/16] fix: add an id to `My Websites` content menu item --- src/gui/src/UI/UIDesktop.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/gui/src/UI/UIDesktop.js b/src/gui/src/UI/UIDesktop.js index 963fff321..19f5b1cb3 100644 --- a/src/gui/src/UI/UIDesktop.js +++ b/src/gui/src/UI/UIDesktop.js @@ -1513,6 +1513,7 @@ $(document).on('click', '.user-options-menu-btn', async function(e){ //-------------------------------------------------- { html: i18n('my_websites'), + id: 'my_websites', onClick: async function(){ UIWindowMyWebsites(); } From 67ca4ccf20fd714848121192d5ae7c41f3763da4 Mon Sep 17 00:00:00 2001 From: jelveh Date: Fri, 29 Nov 2024 19:40:54 -0800 Subject: [PATCH 10/16] fix: add id to the setting menu item in user option menu --- src/gui/src/UI/UIDesktop.js | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/gui/src/UI/UIDesktop.js b/src/gui/src/UI/UIDesktop.js index 19f5b1cb3..20846955b 100644 --- a/src/gui/src/UI/UIDesktop.js +++ b/src/gui/src/UI/UIDesktop.js @@ -1509,6 +1509,16 @@ $(document).on('click', '.user-options-menu-btn', async function(e){ items: [ ...items, //-------------------------------------------------- + // Settings + //-------------------------------------------------- + { + html: i18n('settings'), + id: 'settings', + onClick: async function(){ + UIWindowSettings(); + } + }, + //-------------------------------------------------- // My Websites //-------------------------------------------------- { @@ -1519,15 +1529,6 @@ $(document).on('click', '.user-options-menu-btn', async function(e){ } }, //-------------------------------------------------- - // Settings - //-------------------------------------------------- - { - html: i18n('settings'), - onClick: async function(){ - UIWindowSettings(); - } - }, - //-------------------------------------------------- // Task Manager //-------------------------------------------------- { From badc654968c50da5e34bc29b2a1242beec229ab8 Mon Sep 17 00:00:00 2001 From: jelveh Date: Sat, 30 Nov 2024 11:13:01 -0800 Subject: [PATCH 11/16] add i18n entries for billing and offerings --- src/gui/src/i18n/translations/en.js | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/gui/src/i18n/translations/en.js b/src/gui/src/i18n/translations/en.js index ddbd38c23..abb459da6 100644 --- a/src/gui/src/i18n/translations/en.js +++ b/src/gui/src/i18n/translations/en.js @@ -360,6 +360,25 @@ const en = { 'Owner': 'Owner', "You can't share with yourself.": `You can't share with yourself.`, 'This user already has access to this item': 'This user already has access to this item', + + // Billing + 'billing.change_payment_method': "Change", + 'billing.cancel': "Cancel", + 'billing.download_invoice': "Download", + 'billing.payment_method': "Payment Method", + 'billing.payment_method_updated': "Payment method updated!", + 'billing.confirm_payment_method': 'Confirm Payment Method', + 'billing.payment_history': "Payment History", + 'billing.refunded': "Refunded", + 'billing.paid': "Paid", + 'billing.ok': "OK", + 'billing.confirm_payment_method': 'Confirm Payment Method', + 'billing.resume_subscription': 'Resume Subscription', + 'billing.subscription_cancelled': 'Your subscription has been canceled.', + 'billing.subscription_cancelled_description': 'You will still have access to your subscription until the end of this billing period.', + 'billing.offering.free': 'Free', + 'billing.offering.pro': 'Professional', + 'billing.offering.business': 'Business', } }; From f672c2824545f90f6efb998d5f0f14518235b88e Mon Sep 17 00:00:00 2001 From: enweazudaniel Date: Sat, 30 Nov 2024 21:16:36 +0100 Subject: [PATCH 12/16] Update ig.js --- src/gui/src/i18n/translations/ig.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/gui/src/i18n/translations/ig.js b/src/gui/src/i18n/translations/ig.js index c6157e03f..0a5eb9640 100644 --- a/src/gui/src/i18n/translations/ig.js +++ b/src/gui/src/i18n/translations/ig.js @@ -349,10 +349,10 @@ const ig = { "change": "gbanwee", "clock_visibility": "Ihe ngosi elekere", - "reading": "gụgụ %strong%", + "reading": "ogụgụ %strong%", "writing": "Na-ede %strong%", - "unzipping": "mkpọpu %strong%", - "sequencing": "Ịtọgharị n’usoro %strong%", + "unzipping": "na mkpọpu ya %strong%", + "sequencing": "usoro %strong%", "zipping": "zipụ %strong%", "Editor": "Onye nchịgharị", "Viewer": "Onye na-ekiri", From 88339c4044da7b2f97a604432580216b11507653 Mon Sep 17 00:00:00 2001 From: jelveh Date: Sat, 30 Nov 2024 17:40:54 -0800 Subject: [PATCH 13/16] add more billing keys for i18n --- src/gui/src/i18n/translations/en.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/gui/src/i18n/translations/en.js b/src/gui/src/i18n/translations/en.js index abb459da6..1dde90d1e 100644 --- a/src/gui/src/i18n/translations/en.js +++ b/src/gui/src/i18n/translations/en.js @@ -379,6 +379,11 @@ const en = { 'billing.offering.free': 'Free', 'billing.offering.pro': 'Professional', 'billing.offering.business': 'Business', + 'billing.cloud_storage': 'Cloud Storage', + 'billing.ai_access': 'AI Access', + 'billing.bandwidth': 'Bandwidth', + 'billing.apps_and_games': 'Apps & Games', + 'billing.upgrade_to_pro': 'Upgrade to %strong%', } }; From b8748639864e11b9939d1d2c906e87448a5e1378 Mon Sep 17 00:00:00 2001 From: jelveh Date: Sat, 30 Nov 2024 23:01:04 -0800 Subject: [PATCH 14/16] Update signup.js --- src/backend/src/routers/signup.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/backend/src/routers/signup.js b/src/backend/src/routers/signup.js index 75ecad056..3d156501d 100644 --- a/src/backend/src/routers/signup.js +++ b/src/backend/src/routers/signup.js @@ -239,15 +239,15 @@ module.exports = eggspress(['/signup'], { // audit_metadata JSON.stringify(audit_metadata), // signup_ip - req.connection.remoteAddress, + req.connection.remoteAddress ?? null, // signup_ip_fwd - req.headers['x-forwarded-for'], + req.headers['x-forwarded-for'] ?? null, // signup_user_agent - req.headers['user-agent'], + req.headers['user-agent'] ?? null, // signup_origin - req.headers['origin'], + req.headers['origin'] ?? null, // signup_server - config.server_id, + config.server_id ?? null, ] ); From e056fafc5041234f3ae94af8c7f5f554010992c9 Mon Sep 17 00:00:00 2001 From: jelveh Date: Sun, 1 Dec 2024 10:10:30 -0800 Subject: [PATCH 15/16] clean up unsed imports --- src/backend/src/routers/get-launch-apps.js | 1 - src/backend/src/routers/signup.js | 3 --- src/backend/src/routers/writeFile.js | 1 - 3 files changed, 5 deletions(-) diff --git a/src/backend/src/routers/get-launch-apps.js b/src/backend/src/routers/get-launch-apps.js index 754f7bd1c..1c8b0da89 100644 --- a/src/backend/src/routers/get-launch-apps.js +++ b/src/backend/src/routers/get-launch-apps.js @@ -20,7 +20,6 @@ const express = require('express'); const router = express.Router(); const auth = require('../middleware/auth.js'); -const config = require('../config'); const { get_app } = require('../helpers.js'); const { DB_READ } = require('../services/database/consts.js'); diff --git a/src/backend/src/routers/signup.js b/src/backend/src/routers/signup.js index 3d156501d..51644e5f9 100644 --- a/src/backend/src/routers/signup.js +++ b/src/backend/src/routers/signup.js @@ -17,14 +17,11 @@ * along with this program. If not, see . */ "use strict" -const express = require('express'); -const router = new express.Router(); const {get_taskbar_items, generate_random_username, generate_system_fsentries, send_email_verification_code, send_email_verification_token, username_exists, invalidate_cached_user_by_id, get_user } = require('../helpers'); const config = require('../config'); const eggspress = require('../api/eggspress'); const { Context } = require('../util/context'); const { DB_WRITE } = require('../services/database/consts'); -const { can } = require('../util/langutil'); // -----------------------------------------------------------------------// // POST /signup diff --git a/src/backend/src/routers/writeFile.js b/src/backend/src/routers/writeFile.js index 7e42ec6fb..b913a925c 100644 --- a/src/backend/src/routers/writeFile.js +++ b/src/backend/src/routers/writeFile.js @@ -18,7 +18,6 @@ */ "use strict" const express = require('express'); -const router = new express.Router(); const {uuid2fsentry, validate_signature_auth, get_url_from_req, sign_file} = require('../helpers'); const fs = require('../middleware/fs.js'); const { NodePathSelector, NodeUIDSelector } = require('../filesystem/node/selectors'); From 3d2648e4ec512b83458dce9b148b3b0d44b32c3a Mon Sep 17 00:00:00 2001 From: KernelDeimos Date: Sun, 1 Dec 2024 15:29:35 -0500 Subject: [PATCH 16/16] chore: update package-lock.json --- package-lock.json | 32 +++++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 93984e84a..e1a541534 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7800,9 +7800,9 @@ } }, "node_modules/axios": { - "version": "1.7.7", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.7.tgz", - "integrity": "sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==", + "version": "1.7.8", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.8.tgz", + "integrity": "sha512-Uu0wb7KNqK2t5K+YQyVCLM76prD5sRFjKHbJYCP1J7JFGEQ6nN7HWn9+04LAeiJ3ji54lgS/gZCH1oxyrf1SPw==", "dependencies": { "follow-redirects": "^1.15.6", "form-data": "^4.0.0", @@ -8634,6 +8634,10 @@ "resolved": "tools/comment-parser", "link": true }, + "node_modules/comment-writer": { + "resolved": "tools/comment-writer", + "link": true + }, "node_modules/commondir": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", @@ -16842,6 +16846,14 @@ "integrity": "sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==", "license": "MIT" }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/wordwrap": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", @@ -17693,6 +17705,20 @@ "node": ">= 14.16" } }, + "tools/comment-writer": { + "version": "1.0.0", + "license": "AGPL-3.0-only", + "dependencies": { + "axios": "^1.7.8", + "console-table-printer": "^2.12.1", + "dedent": "^1.5.3", + "diff-match-patch": "^1.0.5", + "enquirer": "^2.4.1", + "js-levenshtein": "^1.1.6", + "word-wrap": "^1.2.5", + "yaml": "^2.4.5" + } + }, "tools/file-walker": { "version": "1.0.0", "license": "AGPL-3.0-only"