Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: openai translations #467

Merged
merged 3 commits into from
Aug 5, 2024
Merged

Conversation

Kodylow
Copy link
Member

@Kodylow Kodylow commented Aug 5, 2024

Used gpt-4o-mini for new translations

Summary by CodeRabbit

  • New Features

    • Introduced multiple new localization files for various languages, enhancing user accessibility for Catalan, German, French, Hungarian, Italian, Japanese, Korean, Portuguese, Russian, and Simplified Chinese.
    • Expanded language support within the application to cater to a broader audience.
  • Bug Fixes

    • Improved clarity and consistency of Spanish translations for better user experience.
  • Chores

    • Enhanced translation functionalities by integrating the OpenAI library, improving performance and error handling.

@Kodylow Kodylow requested review from a team as code owners August 5, 2024 19:51
Copy link
Contributor

coderabbitai bot commented Aug 5, 2024

Walkthrough

Walkthrough

This update significantly enhances the application's localization support by adding user interface translations in multiple languages, including Catalan, German, Spanish, French, Hungarian, Italian, Japanese, Korean, Portuguese, Russian, and Chinese. It also integrates the OpenAI API into the translation script, streamlining the translation process for improved functionality. These changes aim to create a more inclusive and user-friendly experience for diverse demographics.

Changes

File(s) Change Summary
.../languages/*.json New localization files added for multiple languages (Catalan, German, French, Hungarian, Italian, Japanese, Korean, Portuguese, Russian, Simplified Chinese) and updates to Spanish and Korean for clarity.
.../languages/index.ts Expanded languages array to include new language entries.
.../package.json Added OpenAI dependency for enhanced translation functionality.
.../scripts/translate.js Replaced old translation mechanism with OpenAI API integration; added functions for improved translation handling.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant App
    participant OpenAI

    User->>App: Request translation
    App->>OpenAI: Send text for translation
    OpenAI-->>App: Return translated text
    App-->>User: Display translated text
Loading

Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits

Files that changed from the base of the PR and between f5ac4a2 and e9e4d52.

Files selected for processing (4)
  • apps/gateway-ui/src/languages/es.json (1 hunks)
  • apps/gateway-ui/src/languages/it.json (1 hunks)
  • apps/gateway-ui/src/languages/pt.json (1 hunks)
  • scripts/translate.js (4 hunks)
Files skipped from review due to trivial changes (1)
  • apps/gateway-ui/src/languages/pt.json
Files skipped from review as they are similar to previous changes (2)
  • apps/gateway-ui/src/languages/es.json
  • apps/gateway-ui/src/languages/it.json
Additional context used
Biome
scripts/translate.js

[error] 97-98: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

Additional comments not posted (7)
scripts/translate.js (7)

13-16: Add error handling for package installation.

The installOpenAI function should include error handling to manage potential issues during the package installation process.


18-21: Add error handling for package uninstallation.

The uninstallOpenAI function should include error handling to manage potential issues during the package uninstallation process.


24-27: Move OpenAI client initialization outside the try block.

The OpenAI client initialization should be moved outside the try block to ensure it is always executed, even if an error occurs later in the function.


56-83: Optimize recursive call in fillMissingKeys.

The recursive call to fillMissingKeys can be optimized to avoid redundant object creation.


85-108: Use optional chaining for safer access.

Change to an optional chain for safer access to nested properties.

Tools
Biome

[error] 97-98: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


110-126: LGTM!

The retryWithExponentialBackoff function is well-implemented and handles retries effectively.


131-137: LGTM!

The main function ensures proper setup and teardown of the OpenAI package.


Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai generate interesting stats about this repository and render them as a table.
    • @coderabbitai show all the console.log statements in this repository.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (invoked as PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Additionally, you can add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 11

Comment on lines 86 to 87
response &&
response.choices &&
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use optional chaining for safer access.

Change to an optional chain for safer access to nested properties.

-    response.choices &&
+    response?.choices &&
Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
response &&
response.choices &&
response?.choices &&
Tools
Biome

[error] 86-87: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

Comment on lines +2 to +3
"card_header": "saldo de eCash",
"sentence": "Denominado en Sats",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ensure consistency in capitalization.

The term "saldo de eCash" should be capitalized for consistency with other headers.

-  "card_header": "saldo de eCash",
+  "card_header": "Saldo de eCash",
Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"card_header": "saldo de eCash",
"sentence": "Denominado en Sats",
"card_header": "Saldo de eCash",
"sentence": "Denominado en Sats",

Comment on lines 26 to 28
"card_header": "saldo de eCash",
"sentence": "Denominado en Sats",
"your-balance": "Su saldo de eCash en esta federación:"
"your-balance": "Tu saldo de eCash en esta federación:"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ensure consistency in capitalization.

The term "saldo de eCash" should be capitalized for consistency with other headers.

-    "card_header": "saldo de eCash",
+    "card_header": "Saldo de eCash",
Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"card_header": "saldo de eCash",
"sentence": "Denominado en Sats",
"your-balance": "Su saldo de eCash en esta federación:"
"your-balance": "Tu saldo de eCash en esta federación:"
"card_header": "Saldo de eCash",
"sentence": "Denominado en Sats",
"your-balance": "Tu saldo de eCash en esta federación:"

"amount-label": "Montant (sats) :",
"amount-placeholder": "Ingresa la cantidad en sats",
"card-header": "Retirar Bitcoin",
"close": "Закрыть",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Translation inconsistency: Close button

The translation for "close" is in Russian instead of Italian.

-  "close": "Закрыть",
+  "close": "Chiudi",
Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"close": "Закрыть",
"close": "Chiudi",

@@ -0,0 +1,131 @@
{
"address-label": "Tu dirección:",
"address-placeholder": "Введите ваш btc-адрес",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Translation inconsistency: Address placeholder

The placeholder text for the address is in Russian instead of Italian.

-  "address-placeholder": "Введите ваш btc-адрес",
+  "address-placeholder": "Inserisci il tuo indirizzo BTC",
Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"address-placeholder": "Введите ваш btc-адрес",
"address-placeholder": "Inserisci il tuo indirizzo BTC",

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like this russitalian snuck through

"close": "Закрыть",
"confirm-withdraw": "Confirmar Retiro",
"error": "Errore",
"error-address": "Die Menge oder die Adresse darf nicht leer sein",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Translation inconsistency: Error address

The translation for the error message is in German instead of Italian.

-  "error-address": "Die Menge oder die Adresse darf nicht leer sein",
+  "error-address": "L'importo o l'indirizzo non possono essere vuoti",
Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"error-address": "Die Menge oder die Adresse darf nicht leer sein",
"error-address": "L'importo o l'indirizzo non possono essere vuoti",

"amount-label": "Montant (sats) :",
"amount-placeholder": "Ingresa la cantidad en sats",
"card-header": "Retirar Bitcoin",
"close": "Закрыть",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Translation inconsistency: Close button

The translation for "close" is in Russian instead of Italian.

-  "close": "Закрыть",
+  "close": "Chiudi",
Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"close": "Закрыть",
"close": "Chiudi",

"withdraw": "Retirar",
"withdraw-all": "Retirar todo",
"withdrawal-created": "Retiro creado.",
"withdrawal-created-description": "Bitte überprüfen Sie Ihre Transaktionshistorie",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Translation inconsistency: Withdrawal created description

The translation for the withdrawal created description is in German instead of Italian.

-  "withdrawal-created-description": "Bitte überprüfen Sie Ihre Transaktionshistorie",
+  "withdrawal-created-description": "Si prega di controllare la cronologia delle transazioni",
Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"withdrawal-created-description": "Bitte überprüfen Sie Ihre Transaktionshistorie",
"withdrawal-created-description": "Si prega di controllare la cronologia delle transazioni",

"connection-string-placeholder": "Colar código de convite da federação",
"heading": "Conéctate a una federación usando un código de invitación",
"information-bar-text": "El número de federaciones a las que puedes conectarte está limitado a una. La conexión a múltiples federaciones será compatible pronto.",
"label": "Строка подключения:",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Translation inconsistency: Connection string label

The translation for the connection string label is in Russian instead of Italian.

-  "label": "Строка подключения:",
+  "label": "Stringa di connessione:",
Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"label": "Строка подключения:",
"label": "Stringa di connessione:",

"close": "Закрыть",
"confirm-withdraw": "Confirmar Retiro",
"error": "Erro",
"error-address": "Der Betrag oder die Adresse dürfen nicht leer sein",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Translation inconsistency: Error address

The translation for the error message is in German instead of Italian.

-  "error-address": "Der Betrag oder die Adresse dürfen nicht leer sein",
+  "error-address": "L'importo o l'indirizzo non possono essere vuoti",
Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"error-address": "Der Betrag oder die Adresse dürfen nicht leer sein",
"error-address": "L'importo o l'indirizzo non possono essere vuoti",

package.json Outdated
@@ -21,7 +21,8 @@
"husky": "^9.0.11",
"prettier": "^2.5.1",
"pretty-quick": "^3.1.3",
"turbo": "^1.13.3"
"turbo": "^1.13.3",
"openai": "^4.1.0"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

since most folks won't need this, I think it would be better to make this an optionalDependency. Then you can install it at runtime via:

(example is chatGPT generated)

const { execSync } = require('child_process');

function requireOrInstall(packageName) {
  try {
    // Try to require the package
    return require(packageName);
  } catch (e) {
    if (e.code === 'MODULE_NOT_FOUND') {
      // Package not found, install it
      console.log(`${packageName} not found. Installing...`);
      execSync(`npm install ${packageName}`, { stdio: 'inherit' });

      // Require the package again after installation
      return require(packageName);
    } else {
      throw e;
    }
  }
}

...

const { OpenAI } = requireOrInstall('openai');

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

Comment on lines +24 to +27
const { OpenAI } = require('openai');
const openai = new OpenAI({
apiKey: process.env.OPENAI_API_KEY,
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move OpenAI client initialization outside the try block.

The OpenAI client initialization should be moved outside the try block to ensure it is always executed, even if an error occurs later in the function.

async function translateAndFill() {
  const { OpenAI } = require('openai');
  const openai = new OpenAI({
    apiKey: process.env.OPENAI_API_KEY,
  });

  try {
    for (const srcPath of srcPaths) {
      const srcFile = `${srcPath}/en.json`;
      const srcData = JSON.parse(await fs.readFile(srcFile, 'utf8'));
Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const { OpenAI } = require('openai');
const openai = new OpenAI({
apiKey: process.env.OPENAI_API_KEY,
});
async function translateAndFill() {
const { OpenAI } = require('openai');
const openai = new OpenAI({
apiKey: process.env.OPENAI_API_KEY,
});
try {
for (const srcPath of srcPaths) {
const srcFile = `${srcPath}/en.json`;
const srcData = JSON.parse(await fs.readFile(srcFile, 'utf8'));

Comment on lines +18 to +21
async function uninstallOpenAI() {
console.log('Uninstalling OpenAI package...');
execSync('yarn remove openai', { stdio: 'inherit' });
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add error handling for package uninstallation.

The uninstallOpenAI function should include error handling to manage potential issues during the package uninstallation process.

async function uninstallOpenAI() {
  console.log('Uninstalling OpenAI package...');
-  execSync('yarn remove openai', { stdio: 'inherit' });
+  try {
+    execSync('yarn remove openai', { stdio: 'inherit' });
+  } catch (error) {
+    console.error('Failed to uninstall OpenAI package:', error);
+    throw error;
+  }
}
Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
async function uninstallOpenAI() {
console.log('Uninstalling OpenAI package...');
execSync('yarn remove openai', { stdio: 'inherit' });
}
async function uninstallOpenAI() {
console.log('Uninstalling OpenAI package...');
try {
execSync('yarn remove openai', { stdio: 'inherit' });
} catch (error) {
console.error('Failed to uninstall OpenAI package:', error);
throw error;
}
}

Comment on lines 86 to 107
const prompt = `Translate the following text to ${targetLang}. Return only the translated string, without any additional text or explanations:\n\n${text}`;

const response = await openai.chat.completions.create({
model: 'gpt-4o-mini',
messages: [{ role: 'user', content: prompt }],
temperature: 0.3,
max_tokens: 150,
stream: false,
});

if (
response &&
response.choices &&
response.choices.length > 0 &&
response.choices[0].message
) {
return response.choices[0].message.content
.trim()
.replace(/^["']|["']$/g, '');
} else {
throw new Error('Unexpected response format from OpenAI API');
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use optional chaining for safer access.

Change to an optional chain for safer access to nested properties.

  if (
    response &&
-    response.choices &&
+    response?.choices &&
    response.choices.length > 0 &&
    response.choices[0].message
  ) {
    return response.choices[0].message.content
      .trim()
      .replace(/^["']|["']$/g, '');
  } else {
    throw new Error('Unexpected response format from OpenAI API');
  }
Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const prompt = `Translate the following text to ${targetLang}. Return only the translated string, without any additional text or explanations:\n\n${text}`;
const response = await openai.chat.completions.create({
model: 'gpt-4o-mini',
messages: [{ role: 'user', content: prompt }],
temperature: 0.3,
max_tokens: 150,
stream: false,
});
if (
response &&
response.choices &&
response.choices.length > 0 &&
response.choices[0].message
) {
return response.choices[0].message.content
.trim()
.replace(/^["']|["']$/g, '');
} else {
throw new Error('Unexpected response format from OpenAI API');
}
const prompt = `Translate the following text to ${targetLang}. Return only the translated string, without any additional text or explanations:\n\n${text}`;
const response = await openai.chat.completions.create({
model: 'gpt-4o-mini',
messages: [{ role: 'user', content: prompt }],
temperature: 0.3,
max_tokens: 150,
stream: false,
});
if (
response &&
response?.choices &&
response.choices.length > 0 &&
response.choices[0].message
) {
return response.choices[0].message.content
.trim()
.replace(/^["']|["']$/g, '');
} else {
throw new Error('Unexpected response format from OpenAI API');
}
Tools
Biome

[error] 97-98: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

Comment on lines +13 to +16
async function installOpenAI() {
console.log('Installing OpenAI package...');
execSync('yarn add openai', { stdio: 'inherit' });
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add error handling for package installation.

The installOpenAI function should include error handling to manage potential issues during the package installation process.

async function installOpenAI() {
  console.log('Installing OpenAI package...');
-  execSync('yarn add openai', { stdio: 'inherit' });
+  try {
+    execSync('yarn add openai', { stdio: 'inherit' });
+  } catch (error) {
+    console.error('Failed to install OpenAI package:', error);
+    throw error;
+  }
}
Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
async function installOpenAI() {
console.log('Installing OpenAI package...');
execSync('yarn add openai', { stdio: 'inherit' });
}
async function installOpenAI() {
console.log('Installing OpenAI package...');
try {
execSync('yarn add openai', { stdio: 'inherit' });
} catch (error) {
console.error('Failed to install OpenAI package:', error);
throw error;
}
}

Comment on lines +56 to +83
async function fillMissingKeys(srcObj, targetObj, lang, path = '') {
const updatedObj = { ...targetObj };
for (const key in srcObj) {
const newPath = path ? `${path}.${key}` : key;

if (typeof srcObj[key] === 'object' && srcObj[key] !== null) {
targetObj[key] = targetObj[key] || {};
await fillMissingKeys(
if (!updatedObj[key] || typeof updatedObj[key] !== 'object') {
updatedObj[key] = {};
}
updatedObj[key] = await fillMissingKeys(
srcObj[key],
targetObj[key],
updatedObj[key],
lang,
newPath,
targetFile
newPath
);
} else if (targetObj[key] === undefined) {
} else if (updatedObj[key] === undefined) {
console.log(`Translating and adding missing key: ${newPath}`);
try {
const translation = await translate(srcObj[key], { to: lang });
targetObj[key] = translation.text;
// Write the updated data back to the file after each translation
await fs.writeFile(
targetFile,
JSON.stringify(targetObj, null, 2),
'utf8'
);
// Introduce a delay between requests to avoid hitting the rate limit
await delay(1000);
} catch (error) {
console.error(`Error translating key: ${newPath}`, error);
if (error.message.includes('Too Many Requests')) {
console.log('Hit rate limit, delaying further requests...');
await delay(3000);
}
await retryWithExponentialBackoff(async () => {
const translation = await translateWithOpenAI(srcObj[key], lang);
updatedObj[key] = translation;
});
} else {
console.log(`Skipping key: ${newPath}`);
}
}

return updatedObj;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Optimize recursive call in fillMissingKeys.

The recursive call to fillMissingKeys can be optimized to avoid redundant object creation.

async function fillMissingKeys(srcObj, targetObj, lang, path = '') {
  const updatedObj = { ...targetObj };
  for (const key in srcObj) {
    const newPath = path ? `${path}.${key}` : key;

    if (typeof srcObj[key] === 'object' && srcObj[key] !== null) {
      if (!updatedObj[key] || typeof updatedObj[key] !== 'object') {
        updatedObj[key] = {};
      }
-      updatedObj[key] = await fillMissingKeys(
-        srcObj[key],
-        updatedObj[key],
-        lang,
-        newPath
-      );
+      await fillMissingKeys(srcObj[key], updatedObj[key], lang, newPath);
    } else if (updatedObj[key] === undefined) {
      console.log(`Translating and adding missing key: ${newPath}`);
      await retryWithExponentialBackoff(async () => {
        const translation = await translateWithOpenAI(srcObj[key], lang);
        updatedObj[key] = translation;
      });
    } else {
      console.log(`Skipping key: ${newPath}`);
    }
  }

  return updatedObj;
}
Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
async function fillMissingKeys(srcObj, targetObj, lang, path = '') {
const updatedObj = { ...targetObj };
for (const key in srcObj) {
const newPath = path ? `${path}.${key}` : key;
if (typeof srcObj[key] === 'object' && srcObj[key] !== null) {
targetObj[key] = targetObj[key] || {};
await fillMissingKeys(
if (!updatedObj[key] || typeof updatedObj[key] !== 'object') {
updatedObj[key] = {};
}
updatedObj[key] = await fillMissingKeys(
srcObj[key],
targetObj[key],
updatedObj[key],
lang,
newPath,
targetFile
newPath
);
} else if (targetObj[key] === undefined) {
} else if (updatedObj[key] === undefined) {
console.log(`Translating and adding missing key: ${newPath}`);
try {
const translation = await translate(srcObj[key], { to: lang });
targetObj[key] = translation.text;
// Write the updated data back to the file after each translation
await fs.writeFile(
targetFile,
JSON.stringify(targetObj, null, 2),
'utf8'
);
// Introduce a delay between requests to avoid hitting the rate limit
await delay(1000);
} catch (error) {
console.error(`Error translating key: ${newPath}`, error);
if (error.message.includes('Too Many Requests')) {
console.log('Hit rate limit, delaying further requests...');
await delay(3000);
}
await retryWithExponentialBackoff(async () => {
const translation = await translateWithOpenAI(srcObj[key], lang);
updatedObj[key] = translation;
});
} else {
console.log(`Skipping key: ${newPath}`);
}
}
return updatedObj;
}
async function fillMissingKeys(srcObj, targetObj, lang, path = '') {
const updatedObj = { ...targetObj };
for (const key in srcObj) {
const newPath = path ? `${path}.${key}` : key;
if (typeof srcObj[key] === 'object' && srcObj[key] !== null) {
if (!updatedObj[key] || typeof updatedObj[key] !== 'object') {
updatedObj[key] = {};
}
await fillMissingKeys(srcObj[key], updatedObj[key], lang, newPath);
} else if (updatedObj[key] === undefined) {
console.log(`Translating and adding missing key: ${newPath}`);
await retryWithExponentialBackoff(async () => {
const translation = await translateWithOpenAI(srcObj[key], lang);
updatedObj[key] = translation;
});
} else {
console.log(`Skipping key: ${newPath}`);
}
}
return updatedObj;
}

Copy link
Collaborator

@alexlwn123 alexlwn123 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

@alexlwn123 alexlwn123 merged commit 0eb9dd2 into fedimint:master Aug 5, 2024
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants