mirror of
https://github.com/danny-avila/LibreChat.git
synced 2025-09-22 06:00:56 +02:00
🧹 chore(/config/): add tsconfig.json & linting (#2680)
This commit is contained in:
parent
bcdddaed72
commit
c83d9d61d4
10 changed files with 187 additions and 141 deletions
|
@ -132,6 +132,13 @@ module.exports = {
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
files: './config/translations/**/*.ts',
|
||||||
|
parser: '@typescript-eslint/parser',
|
||||||
|
parserOptions: {
|
||||||
|
project: './config/translations/tsconfig.json',
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
files: ['./packages/data-provider/specs/**/*.ts'],
|
files: ['./packages/data-provider/specs/**/*.ts'],
|
||||||
parserOptions: {
|
parserOptions: {
|
||||||
|
|
|
@ -1,44 +1,40 @@
|
||||||
import Anthropic from '@anthropic-ai/sdk';
|
import Anthropic from '@anthropic-ai/sdk';
|
||||||
import type * as a from '@anthropic-ai/sdk';
|
import type * as a from '@anthropic-ai/sdk';
|
||||||
import {
|
import { parseParamFromPrompt, genTranslationPrompt } from '~/app/clients/prompts/titlePrompts';
|
||||||
parseParamFromPrompt,
|
|
||||||
genTranslationPrompt,
|
|
||||||
} from '../../api/app/clients/prompts/titlePrompts';
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the initialized Anthropic client.
|
||||||
|
* @returns {Anthropic} The Anthropic client instance.
|
||||||
|
*/
|
||||||
|
export function getClient() {
|
||||||
|
/** @type {Anthropic.default.RequestOptions} */
|
||||||
|
const options = {
|
||||||
|
apiKey: process.env.ANTHROPIC_API_KEY,
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
return new Anthropic(options);
|
||||||
* Get the initialized Anthropic client.
|
}
|
||||||
* @returns {Anthropic} The Anthropic client instance.
|
|
||||||
*/
|
|
||||||
export function getClient() {
|
|
||||||
/** @type {Anthropic.default.RequestOptions} */
|
|
||||||
const options = {
|
|
||||||
apiKey: process.env.ANTHROPIC_API_KEY,
|
|
||||||
};
|
|
||||||
|
|
||||||
return new Anthropic(options);
|
/**
|
||||||
}
|
* This function capitlizes on [Anthropic's function calling training](https://docs.anthropic.com/claude/docs/functions-external-tools).
|
||||||
|
*
|
||||||
|
* @param {Object} params - The parameters for the generation.
|
||||||
|
* @param {string} params.key
|
||||||
|
* @param {string} params.baselineTranslation
|
||||||
|
* @param {string} params.translationPrompt
|
||||||
|
* @param {Array<{ pageContent: string }>} params.context
|
||||||
|
*
|
||||||
|
* @returns {Promise<string | 'New Chat'>} A promise that resolves to the generated conversation title.
|
||||||
|
* In case of failure, it will return the default title, "New Chat".
|
||||||
|
*/
|
||||||
|
export async function translateKeyPhrase({ key, baselineTranslation, translationPrompt, context }) {
|
||||||
|
let translation: string | undefined;
|
||||||
|
const model = 'claude-3-sonnet-20240229';
|
||||||
|
const prompt = genTranslationPrompt(translationPrompt);
|
||||||
|
const system = prompt;
|
||||||
|
|
||||||
/**
|
const translateCompletion = async () => {
|
||||||
* This function capitlizes on [Anthropic's function calling training](https://docs.anthropic.com/claude/docs/functions-external-tools).
|
const content = `Current key: \`${key}\`
|
||||||
*
|
|
||||||
* @param {Object} params - The parameters for the generation.
|
|
||||||
* @param {string} params.key
|
|
||||||
* @param {string} params.baselineTranslation
|
|
||||||
* @param {string} params.translationPrompt
|
|
||||||
* @param {Array<{ pageContent: string }>} params.context
|
|
||||||
*
|
|
||||||
* @returns {Promise<string | 'New Chat'>} A promise that resolves to the generated conversation title.
|
|
||||||
* In case of failure, it will return the default title, "New Chat".
|
|
||||||
*/
|
|
||||||
export async function translateKeyPhrase({ key, baselineTranslation, translationPrompt, context }) {
|
|
||||||
let translation: string | undefined;
|
|
||||||
const model = 'claude-3-sonnet-20240229';
|
|
||||||
const prompt = genTranslationPrompt(translationPrompt);
|
|
||||||
const system = prompt;
|
|
||||||
|
|
||||||
const translateCompletion = async () => {
|
|
||||||
const content = `Current key: \`${key}\`
|
|
||||||
|
|
||||||
Baseline translation: ${baselineTranslation}
|
Baseline translation: ${baselineTranslation}
|
||||||
|
|
||||||
|
@ -50,27 +46,27 @@ import {
|
||||||
|
|
||||||
<invoke>\n<tool_name>submit_translation</tool_name>\n<parameters>\n<translation>Your Translation Here</translation>\n</parameters>\n</invoke>`;
|
<invoke>\n<tool_name>submit_translation</tool_name>\n<parameters>\n<translation>Your Translation Here</translation>\n</parameters>\n</invoke>`;
|
||||||
|
|
||||||
const message: a.Anthropic.MessageParam = { role: 'user', content };
|
const message: a.Anthropic.MessageParam = { role: 'user', content };
|
||||||
const requestOptions: a.Anthropic.MessageCreateParamsNonStreaming = {
|
const requestOptions: a.Anthropic.MessageCreateParamsNonStreaming = {
|
||||||
model,
|
model,
|
||||||
temperature: 0.3,
|
temperature: 0.3,
|
||||||
max_tokens: 1024,
|
max_tokens: 1024,
|
||||||
system,
|
system,
|
||||||
stop_sequences: ['\n\nHuman:', '\n\nAssistant', '</function_calls>'],
|
stop_sequences: ['\n\nHuman:', '\n\nAssistant', '</function_calls>'],
|
||||||
messages: [message],
|
messages: [message],
|
||||||
stream: false,
|
stream: false,
|
||||||
};
|
|
||||||
|
|
||||||
try {
|
|
||||||
const client = getClient();
|
|
||||||
const response = await client.messages.create(requestOptions);
|
|
||||||
const text = response.content[0].text;
|
|
||||||
translation = parseParamFromPrompt(text, 'translation');
|
|
||||||
} catch (e) {
|
|
||||||
console.error('[AnthropicClient] There was an issue generating the translation', e);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
await translateCompletion();
|
try {
|
||||||
return translation;
|
const client = getClient();
|
||||||
}
|
const response = await client.messages.create(requestOptions);
|
||||||
|
const text = response.content[0].text;
|
||||||
|
translation = parseParamFromPrompt(text, 'translation');
|
||||||
|
} catch (e) {
|
||||||
|
console.error('[AnthropicClient] There was an issue generating the translation', e);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
await translateCompletion();
|
||||||
|
return translation;
|
||||||
|
}
|
||||||
|
|
|
@ -3,54 +3,65 @@ import path from 'path';
|
||||||
import { exec } from 'child_process';
|
import { exec } from 'child_process';
|
||||||
|
|
||||||
async function main(baseFilePath: string, languagesDir: string) {
|
async function main(baseFilePath: string, languagesDir: string) {
|
||||||
const { default: baseLanguage } = await import(path.resolve(baseFilePath));
|
const { default: baseLanguage } = await import(path.resolve(baseFilePath));
|
||||||
const files = fs.readdirSync(languagesDir);
|
const files = fs.readdirSync(languagesDir);
|
||||||
|
|
||||||
for (let file of files) {
|
for (const file of files) {
|
||||||
const ext = path.extname(file);
|
const ext = path.extname(file);
|
||||||
if (ext !== '.ts' && ext !== '.tsx') continue; // Only process TypeScript files
|
if (ext !== '.ts' && ext !== '.tsx') {
|
||||||
|
continue;
|
||||||
const filePath = path.resolve(languagesDir, file);
|
|
||||||
if (filePath === baseFilePath) continue; // Skip the base language file
|
|
||||||
|
|
||||||
const { default: otherLanguage } = await import(filePath);
|
|
||||||
let comparisons = {};
|
|
||||||
|
|
||||||
for (let key in otherLanguage) {
|
|
||||||
if (otherLanguage.hasOwnProperty(key) && baseLanguage.hasOwnProperty(key)) {
|
|
||||||
comparisons[key] = {
|
|
||||||
english: baseLanguage[key],
|
|
||||||
translated: otherLanguage[key]
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let fileContent = fs.readFileSync(filePath, 'utf8');
|
|
||||||
const comparisonsObjRegex = /export const comparisons = {[\s\S]*?};/gm;
|
|
||||||
const hasComparisons = comparisonsObjRegex.test(fileContent);
|
|
||||||
const comparisonsExport = `\nexport const comparisons = ${JSON.stringify(comparisons, null, 2)};\n`;
|
|
||||||
|
|
||||||
if (hasComparisons) {
|
|
||||||
fileContent = fileContent.replace(comparisonsObjRegex, comparisonsExport);
|
|
||||||
} else {
|
|
||||||
fileContent = fileContent.trim() + comparisonsExport;
|
|
||||||
}
|
|
||||||
|
|
||||||
fs.writeFileSync(filePath, fileContent); // Write updated content back to file
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Execute ESLint with the --fix option on the entire directory
|
const filePath = path.resolve(languagesDir, file);
|
||||||
exec(`bunx eslint "${languagesDir}" --fix`, (error, stdout, stderr) => {
|
if (filePath === baseFilePath) {
|
||||||
if (error) {
|
continue;
|
||||||
console.error('Error executing ESLint:', error);
|
}
|
||||||
return;
|
|
||||||
}
|
const { default: otherLanguage } = await import(filePath);
|
||||||
if (stderr) {
|
const comparisons = {};
|
||||||
console.error('ESLint stderr:', stderr);
|
|
||||||
return;
|
for (const key in otherLanguage) {
|
||||||
}
|
if (
|
||||||
console.log('ESLint stdout:', stdout);
|
Object.prototype.hasOwnProperty.call(otherLanguage, key) &&
|
||||||
});
|
Object.prototype.hasOwnProperty.call(baseLanguage, key)
|
||||||
|
) {
|
||||||
|
comparisons[key] = {
|
||||||
|
english: baseLanguage[key],
|
||||||
|
translated: otherLanguage[key],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let fileContent = fs.readFileSync(filePath, 'utf8');
|
||||||
|
const comparisonsObjRegex = /export const comparisons = {[\s\S]*?};/gm;
|
||||||
|
const hasComparisons = comparisonsObjRegex.test(fileContent);
|
||||||
|
const comparisonsExport = `\nexport const comparisons = ${JSON.stringify(
|
||||||
|
comparisons,
|
||||||
|
null,
|
||||||
|
2,
|
||||||
|
)};\n`;
|
||||||
|
|
||||||
|
if (hasComparisons) {
|
||||||
|
fileContent = fileContent.replace(comparisonsObjRegex, comparisonsExport);
|
||||||
|
} else {
|
||||||
|
fileContent = fileContent.trim() + comparisonsExport;
|
||||||
|
}
|
||||||
|
|
||||||
|
fs.writeFileSync(filePath, fileContent);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Execute ESLint with the --fix option on the entire directory
|
||||||
|
exec(`bunx eslint "${languagesDir}" --fix`, (error, stdout, stderr) => {
|
||||||
|
if (error) {
|
||||||
|
console.error('Error executing ESLint:', error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (stderr) {
|
||||||
|
console.error('ESLint stderr:', stderr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.log('ESLint stdout:', stdout);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const languagesDir = './client/src/localization/languages';
|
const languagesDir = './client/src/localization/languages';
|
||||||
|
@ -58,15 +69,13 @@ const baseFilePath = path.resolve(languagesDir, 'Eng.ts');
|
||||||
|
|
||||||
main(baseFilePath, languagesDir).catch(console.error);
|
main(baseFilePath, languagesDir).catch(console.error);
|
||||||
|
|
||||||
|
|
||||||
// const prompt = `
|
// const prompt = `
|
||||||
|
|
||||||
// Write a prompt that is mindful of the nuances in the language with respect to its English counterpart, which serves as the baseline for translations. Here are the comparisons between the language translations and their English counterparts:
|
// Write a prompt that is mindful of the nuances in the language with respect to its English counterpart, which serves as the baseline for translations. Here are the comparisons between the language translations and their English counterparts:
|
||||||
|
|
||||||
// ${comparisons}
|
// ${comparisons}
|
||||||
|
|
||||||
|
|
||||||
// Please consider the above comparisons to enhance understanding and guide improvements in translations. Provide insights or suggestions that could help refine the translation process, focusing on cultural and contextual relevance.
|
// Please consider the above comparisons to enhance understanding and guide improvements in translations. Provide insights or suggestions that could help refine the translation process, focusing on cultural and contextual relevance.
|
||||||
|
|
||||||
// Please craft a prompt that can be used to better inform future translations to this language. Write this prompt in the translated language, with all its nuances detected, not in the English.
|
// Please craft a prompt that can be used to better inform future translations to this language. Write this prompt in the translated language, with all its nuances detected, not in the English.
|
||||||
// `;
|
// `;
|
||||||
|
|
|
@ -2,34 +2,34 @@ import dotenv from 'dotenv';
|
||||||
dotenv.config({
|
dotenv.config({
|
||||||
path: './',
|
path: './',
|
||||||
});
|
});
|
||||||
import { OpenAIEmbeddings } from "@langchain/openai";
|
import { OpenAIEmbeddings } from '@langchain/openai';
|
||||||
import { HNSWLib } from "@langchain/community/vectorstores/hnswlib";
|
import { HNSWLib } from '@langchain/community/vectorstores/hnswlib';
|
||||||
import { RecursiveCharacterTextSplitter } from "langchain/text_splitter";
|
import { RecursiveCharacterTextSplitter } from 'langchain/text_splitter';
|
||||||
import * as fs from "fs";
|
import * as fs from 'fs';
|
||||||
import * as path from "path";
|
import * as path from 'path';
|
||||||
|
|
||||||
export const storeEmbeddings = async (modulePath: string) => {
|
export const storeEmbeddings = async (modulePath: string) => {
|
||||||
try {
|
try {
|
||||||
const text = fs.readFileSync(modulePath, "utf8");
|
const text = fs.readFileSync(modulePath, 'utf8');
|
||||||
const textSplitter = new RecursiveCharacterTextSplitter({ chunkSize: 600 });
|
const textSplitter = new RecursiveCharacterTextSplitter({ chunkSize: 600 });
|
||||||
const docs = await textSplitter.createDocuments([text]);
|
const docs = await textSplitter.createDocuments([text]);
|
||||||
const vectorStore = await HNSWLib.fromDocuments(docs, new OpenAIEmbeddings());
|
const vectorStore = await HNSWLib.fromDocuments(docs, new OpenAIEmbeddings());
|
||||||
const directory = `./config/translations/stores/${path.basename(modulePath)}`;
|
const directory = `./config/translations/stores/${path.basename(modulePath)}`;
|
||||||
|
|
||||||
if (!fs.existsSync(directory)) {
|
if (!fs.existsSync(directory)) {
|
||||||
fs.mkdirSync(directory, { recursive: true });
|
fs.mkdirSync(directory, { recursive: true });
|
||||||
console.log(`Directory created: ${directory}`);
|
console.log(`Directory created: ${directory}`);
|
||||||
} else {
|
} else {
|
||||||
console.log(`Directory already exists: ${directory}`);
|
console.log(`Directory already exists: ${directory}`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await vectorStore.save(directory);
|
await vectorStore.save(directory);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(`Error storing embeddings`);
|
console.error('Error storing embeddings');
|
||||||
console.error(error);
|
console.error(error);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
export const loadEmbeddings = async (modulePath: string) => {
|
export const loadEmbeddings = async (modulePath: string) => {
|
||||||
try {
|
try {
|
||||||
|
@ -37,7 +37,7 @@ export const loadEmbeddings = async (modulePath: string) => {
|
||||||
const loadedVectorStore = await HNSWLib.load(directory, new OpenAIEmbeddings());
|
const loadedVectorStore = await HNSWLib.load(directory, new OpenAIEmbeddings());
|
||||||
return loadedVectorStore;
|
return loadedVectorStore;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(`Error loading embeddings`);
|
console.error('Error loading embeddings');
|
||||||
console.error(error);
|
console.error(error);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
|
@ -5,11 +5,13 @@ const baseDirPath = './client/src/localization/languages';
|
||||||
const promptsDirPath = './client/src/localization/prompts/instructions';
|
const promptsDirPath = './client/src/localization/prompts/instructions';
|
||||||
|
|
||||||
async function ensureDirectoryExists(directory: string) {
|
async function ensureDirectoryExists(directory: string) {
|
||||||
return fs.promises.access(directory).catch(() => fs.promises.mkdir(directory, { recursive: true }));
|
return fs.promises
|
||||||
|
.access(directory)
|
||||||
|
.catch(() => fs.promises.mkdir(directory, { recursive: true }));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper function to generate Markdown from an object, recursively if needed
|
// Helper function to generate Markdown from an object, recursively if needed
|
||||||
function generateMarkdownFromObject(obj: any, depth: number = 0): string {
|
function generateMarkdownFromObject(obj: object, depth = 0): string {
|
||||||
if (typeof obj !== 'object' || obj === null) {
|
if (typeof obj !== 'object' || obj === null) {
|
||||||
return String(obj);
|
return String(obj);
|
||||||
}
|
}
|
||||||
|
@ -61,7 +63,8 @@ async function createPromptsForTranslations() {
|
||||||
const files = await fs.promises.readdir(baseDirPath);
|
const files = await fs.promises.readdir(baseDirPath);
|
||||||
|
|
||||||
for (const file of files) {
|
for (const file of files) {
|
||||||
if (!file.includes('Eng.ts')) { // Ensure English or base file is excluded
|
if (!file.includes('Eng.ts')) {
|
||||||
|
// Ensure English or base file is excluded
|
||||||
const filePath = path.join(baseDirPath, file);
|
const filePath = path.join(baseDirPath, file);
|
||||||
const promptContent = await generatePromptForFile(filePath, file);
|
const promptContent = await generatePromptForFile(filePath, file);
|
||||||
const outputFilePath = path.join(promptsDirPath, `${path.basename(file, '.ts')}.md`);
|
const outputFilePath = path.join(promptsDirPath, `${path.basename(file, '.ts')}.md`);
|
||||||
|
|
|
@ -8,21 +8,25 @@ async function readKeysFromFile(filePath: string): Promise<string[]> {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function compareKeys(baseKeys: string[], keysFromOtherFile: string[]): Promise<string[]> {
|
async function compareKeys(baseKeys: string[], keysFromOtherFile: string[]): Promise<string[]> {
|
||||||
const missingKeys = baseKeys.filter(key => !keysFromOtherFile.includes(key));
|
const missingKeys = baseKeys.filter((key) => !keysFromOtherFile.includes(key));
|
||||||
return missingKeys;
|
return missingKeys;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function main(baseFilePath: string, languagesDir: string) {
|
async function main(baseFilePath: string, languagesDir: string) {
|
||||||
const baseKeys = await readKeysFromFile(baseFilePath);
|
const baseKeys = await readKeysFromFile(baseFilePath);
|
||||||
|
|
||||||
const files = fs.readdirSync(languagesDir);
|
const files = fs.readdirSync(languagesDir);
|
||||||
for (const file of files) {
|
for (const file of files) {
|
||||||
const ext = path.extname(file);
|
const ext = path.extname(file);
|
||||||
if (ext !== '.ts' && ext !== '.tsx') continue; // Ensure it's a TypeScript file
|
if (ext !== '.ts' && ext !== '.tsx') {
|
||||||
|
continue;
|
||||||
|
} // Ensure it's a TypeScript file
|
||||||
|
|
||||||
const compareFilePath = path.resolve(languagesDir, file);
|
const compareFilePath = path.resolve(languagesDir, file);
|
||||||
if (compareFilePath === baseFilePath) continue; // Skip the base file
|
if (compareFilePath === baseFilePath) {
|
||||||
|
continue;
|
||||||
|
} // Skip the base file
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const keysFromOtherFile = await readKeysFromFile(compareFilePath);
|
const keysFromOtherFile = await readKeysFromFile(compareFilePath);
|
||||||
const missingKeys = await compareKeys(baseKeys, keysFromOtherFile);
|
const missingKeys = await compareKeys(baseKeys, keysFromOtherFile);
|
||||||
|
|
|
@ -16,11 +16,11 @@ export default async function main(baseFilePath: string, compareFilePath: string
|
||||||
const compareModule = await import(compareFilePath);
|
const compareModule = await import(compareFilePath);
|
||||||
const compareKeys = Object.keys(compareModule.default);
|
const compareKeys = Object.keys(compareModule.default);
|
||||||
|
|
||||||
const missingKeys = baseKeys.filter(key => !compareKeys.includes(key));
|
const missingKeys = baseKeys.filter((key) => !compareKeys.includes(key));
|
||||||
if (missingKeys.length > 0) {
|
if (missingKeys.length > 0) {
|
||||||
const keyTranslations = {};
|
const keyTranslations = {};
|
||||||
for (const key of missingKeys) {
|
for (const key of missingKeys) {
|
||||||
const baselineTranslation = baseModule.default[key] || "No baseline translation available";
|
const baselineTranslation = baseModule.default[key] || 'No baseline translation available';
|
||||||
const result = await processMissingKey({
|
const result = await processMissingKey({
|
||||||
key,
|
key,
|
||||||
baselineTranslation,
|
baselineTranslation,
|
||||||
|
@ -31,8 +31,11 @@ export default async function main(baseFilePath: string, compareFilePath: string
|
||||||
}
|
}
|
||||||
|
|
||||||
const outputDir = path.dirname(compareFilePath);
|
const outputDir = path.dirname(compareFilePath);
|
||||||
const outputFileName = `${path.basename(compareFilePath, path.extname(compareFilePath))}_missing_keys.json`;
|
const outputFileName = `${path.basename(
|
||||||
|
compareFilePath,
|
||||||
|
path.extname(compareFilePath),
|
||||||
|
)}_missing_keys.json`;
|
||||||
const outputFilePath = path.join(outputDir, outputFileName);
|
const outputFilePath = path.join(outputDir, outputFileName);
|
||||||
fs.writeFileSync(outputFilePath, JSON.stringify(keyTranslations, null, 2));
|
fs.writeFileSync(outputFilePath, JSON.stringify(keyTranslations, null, 2));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,7 @@ export async function processLanguageModule(moduleName: string, modulePath: stri
|
||||||
await storeEmbeddings(modulePath);
|
await storeEmbeddings(modulePath);
|
||||||
vectorStoreMap[moduleName] = await loadEmbeddings(modulePath);
|
vectorStoreMap[moduleName] = await loadEmbeddings(modulePath);
|
||||||
const baseKeys = Object.keys((await import(modulePath)).default);
|
const baseKeys = Object.keys((await import(modulePath)).default);
|
||||||
console.log(`Keys in module: ${moduleName}:`, baseKeys.length)
|
console.log(`Keys in module: ${moduleName}:`, baseKeys.length);
|
||||||
missingKeyMap[moduleName] = 0;
|
missingKeyMap[moduleName] = 0;
|
||||||
return prompt;
|
return prompt;
|
||||||
}
|
}
|
||||||
|
@ -30,8 +30,11 @@ export async function processMissingKey({
|
||||||
baselineTranslation,
|
baselineTranslation,
|
||||||
moduleName,
|
moduleName,
|
||||||
translationPrompt,
|
translationPrompt,
|
||||||
} : {
|
}: {
|
||||||
key: string, baselineTranslation: string, moduleName: string, translationPrompt: string
|
key: string;
|
||||||
|
baselineTranslation: string;
|
||||||
|
moduleName: string;
|
||||||
|
translationPrompt: string;
|
||||||
}) {
|
}) {
|
||||||
missingKeyMap[moduleName]++;
|
missingKeyMap[moduleName]++;
|
||||||
const vectorStore = vectorStoreMap[moduleName];
|
const vectorStore = vectorStoreMap[moduleName];
|
||||||
|
@ -42,6 +45,6 @@ export async function processMissingKey({
|
||||||
translationPrompt,
|
translationPrompt,
|
||||||
context,
|
context,
|
||||||
});
|
});
|
||||||
console.log(`"${key}": "${translation}",\n`)
|
console.log(`"${key}": "${translation}",\n`);
|
||||||
return translation;
|
return translation;
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,11 +6,15 @@ async function scanDirectory(baseFilePath: string, languagesDir: string) {
|
||||||
const files = fs.readdirSync(languagesDir);
|
const files = fs.readdirSync(languagesDir);
|
||||||
for (const file of files) {
|
for (const file of files) {
|
||||||
const ext = path.extname(file);
|
const ext = path.extname(file);
|
||||||
if (ext !== '.ts' && ext !== '.tsx') continue;
|
if (ext !== '.ts' && ext !== '.tsx') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
const compareFilePath = path.resolve(languagesDir, file);
|
const compareFilePath = path.resolve(languagesDir, file);
|
||||||
if (compareFilePath === baseFilePath) continue;
|
if (compareFilePath === baseFilePath) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
await main(baseFilePath, compareFilePath);
|
await main(baseFilePath, compareFilePath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
17
config/translations/tsconfig.json
Normal file
17
config/translations/tsconfig.json
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"noImplicitAny": false,
|
||||||
|
"baseUrl": ".",
|
||||||
|
"outDir": "./dist",
|
||||||
|
"strict": true,
|
||||||
|
"moduleResolution": "node",
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"target": "es6",
|
||||||
|
"module": "esnext",
|
||||||
|
"lib": ["dom", "es6"],
|
||||||
|
"paths": {
|
||||||
|
"~/*": ["../../api/*"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"include": ["*.ts"]
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue