Skip to content

yxw007/translate

Repository files navigation

Translate

English | 简体中文

GitHub top language GitHub License NPM Version Codecov GitHub Actions Workflow Status

❓ Why do I need translate?

  1. a lot of translation tool libraries on the market, basically not very well-maintained
  2. not written by ts, not friendly enough when using the prompts
  3. single function, does not support batch translation Or only support a translation engine
  4. ...

Note: Translate helps you to solve all the above problems, and will expand more in the future!

✨ Features

  • 🌐 Multi-environment support: Node environment, browser environment
  • Easy to use: provides a concise API, you can easily help you to translate
  • 🌍 Multi-translation engine support: Google, Azure Translate, Amazon Translate, Deepl, Baidu, OpenAI, etc. (will expand more in the future)
  • 🛠️ typescript: friendlier code hints and quality assurance
  • 📦 Batch translation: one api request, translate more content, reduce http requests to improve translation efficiency
  • 🔓 completely open source.

Special reminder: although the library has supported the use of the browser environment, but please only use the google engine translation (google does not need key), the use of other translation engine need to configure the key, the use of the front-end will lead to key leakage, do not do it

Browser bundles exclude Node-only helpers such as filesystem utilities. Keep browser usage focused on engines that are safe to expose client-side.

💻Translation engines, integration cases

Name Support Description
google Commissioned and ready for use
azure translate Commissioned and ready for use
amazon translate Commissioned and ready for use
baidu Commissioned and ready for use
deepl Commissioned and ready for use
openai Commissioned and ready for use
tencent Commissioned and ready for use
yandex I have not tuned in as I do not have a bank account supported by the platform (help from those who are in a position to do so is welcome and appreciated)

🛠 Development

This project now uses rolldown, oxlint, and oxfmt instead of rollup, eslint, and prettier.

pnpm build
pnpm lint
pnpm lint:fix
pnpm format
pnpm format:check
pnpm test
  • pnpm build: builds Node and browser bundles with rolldown, then emits .d.ts files with TypeScript.
  • pnpm lint: runs oxlint and oxfmt --check.
  • pnpm lint:fix: applies oxlint --fix and formats files with oxfmt.
  • pnpm format: formats the repository with oxfmt.
  • pnpm test: runs stable offline-safe tests.

Integration tests that require real network access and third-party credentials are disabled by default. To run them manually, set RUN_INTEGRATION_TESTS=true before running pnpm test.

  • Bash

    RUN_INTEGRATION_TESTS=true pnpm test
  • PowerShell

    $env:RUN_INTEGRATION_TESTS = "true"
    pnpm test

🚀 Install

  • npm

    npm install @yxw007/translate
  • yarn

    yarn add @yxw007/translate
  • pnpm

    pnpm i @yxw007/translate

📖 Usage

Node

  • ESM

    import { translator, engines } from "@yxw007/translate";
  • Commonjs

    const { translator, engines } = required("@yxw007/translate");
  • Translation examples

    translator.addEngine(engines.google);
    const res1 = await translator.translate("hello", { from: "en", to: "zh" });
    console.log(res1);
    
    const res2 = await translator.translate(["hello", "good"], { from: "en", to: "zh", engine: "google" });
    console.log(res2);

    Output results

    ['你好']
    ["你好", "好的"]
  • Language detection examples

    translator.addEngine(engines.google);
    const res1 = await translator.checkLanguage("hello", { engine: "google" });
    console.log(res1);

    Output results

    en

Browser

use jsDelivr CDN

  • development

    <script src="https://cdn.jsdelivr.net/npm/@yxw007/translate@0.0.7/dist/browser/index.umd.js"></script>
  • production

    <script src="https://cdn.jsdelivr.net/npm/@yxw007/translate@0.0.7/dist/browser/index.umd.min.js"></script>
  • example

    <!DOCTYPE html>
    ...
    
    <head>
      ...
      <script src="https://cdn.jsdelivr.net/npm/@yxw007/translate@0.0.7/dist/browser/index.umd.js"></script>
    </head>
    
    <body>
      <script>
        (async () => {
          const { engines, translator } = translate;
          translator.addEngine(engines.google);
          const res = await translator.translate("hello", { from: "en", to: "zh" });
          console.log(res);
        })();
      </script>
    </body>
    
    </html>

📚 API

Translator

class Translator {
  private engines: Map<string, Engine>;
  constructor() {
    this.engines = new Map<string, Engine>();
  }
  /**
   * This method is obsolete, please use the addEngine method
   * @param engine {@link Engine}  instance
   * @deprecated Use {@link addEngine} instead.
   */
  use(engine: Engine) {
    this.addEngine(engine);
  }
  addEngine(engine: Engine) {
   ...
  }
  removeEngine(engineName: string) {
   ...
  }
  getFromLanguages(engineName: string) {
   ...
  }
  getToLanguages(engineName: string) {
   ...
  }
  translate<T extends Engines>(text: string | string[], options: TranslateOptions<T>) {
    ...
  }
}

use

Add a translation engine to transitorion engine to translator

type Engine = {
  name: string;
  getFromLanguages(): Record<string, string>;
  getToLanguages(): Record<string, string>;
  normalFromLanguage(language?: string): string;
  normalToLanguage(language?: string): string;
  translate(text: string | string[], options: EngineTranslateOptions) {
};

translate

You can pass a text or pass a text array, which will return a translated Promise<string[]>

translate<T extends Engines>(text: string | string[], options: TranslateOptions<T>)

getFromLanguages / getToLanguages

Read the language list for the specified engine.

translator.getFromLanguages("google");
translator.getToLanguages("google");

TranslateOptions

export interface TranslateOptions {
  from?: FromLanguage<T>;
  to: ToLanguage<T>;
  engine?: Engines;
  /**
   * Cache time in milliseconds
   */
  cache_time?: number;
  /**
   * Domain to use for translation
   */
  domain?: string;
}

Note: Each engine now maintains its own from/to language configuration. You can inspect the engine-scoped configuration under src/language/engines/*.

Each translation of Engine's Option

BaseEngineOption

interface BaseEngineOption {
  fromLanguages?: Record<string, string>;
  toLanguages?: Record<string, string>;
}

fromLanguages / toLanguages are only initialization options for engine factories that need custom language tables. They are not exposed as public fields on the engine instance.

Custom Engine

import { Translator, type Engine } from "@yxw007/translate";

const translator = new Translator();

const fromLanguages = { Auto: "auto", English: "en" };
const toLanguages = { Chinese: "zh", Japanese: "ja" };

const customEngine: Engine = {
  name: "custom",
  getFromLanguages() {
    return fromLanguages;
  },
  getToLanguages() {
    return toLanguages;
  },
  normalFromLanguage(language) {
    if (!language || language === "auto") return "auto";
    return fromLanguages[language as keyof typeof fromLanguages] ?? "";
  },
  normalToLanguage(language) {
    if (!language) return "";
    return toLanguages[language as keyof typeof toLanguages] ?? "";
  },
  async translate(text, options) {
    const list = Array.isArray(text) ? text : [text];
    return list.map((item) => `[${options.from}->${options.to}] ${item}`);
  },
};

translator.addEngine(customEngine);

Built-in engines are directly referenced:

translator.addEngine(engines.google);

AzureEngineOption

interface AzureEngineOption extends BaseEngineOption {
  key: string;
  region: string;
}

Note: Option Param, please get it from the corresponding platform

AmazonEngineOption

interface AmazonEngineOption extends BaseEngineOption {
  region: string;
  accessKeyId: string;
  secretAccessKey: string;
}

Note: Option Param, please get it from the corresponding platform

BaiduEngineOption

export interface BaiduEngineOption extends BaseEngineOption {
  appId: string;
  secretKey: string;
}

Note: Option Param, please get it from the corresponding platform

DeeplEngineOption

export interface DeeplEngineOption {
  key: string;
}

Note: Option Param, please get it from the corresponding platform

OpenAIEngineOption

export interface OpenAIEngineOption {
  apiKey: string;
  model: OpenAIModel;
}

export const OPEN_AI_MODELS = [
  "o1-preview",
  "o1-preview-2024-09-12",
  "o1-mini-2024-09-12",
  "o1-mini",
  "dall-e-2",
  "gpt-3.5-turbo",
  "gpt-3.5-turbo-0125",
  "babbage-002",
  "davinci-002",
  "dall-e-3",
  "text-embedding-3-large",
  "gpt-3.5-turbo-16k",
  "tts-1-hd-1106",
  "text-embedding-ada-002",
  "text-embedding-3-small",
  "tts-1-hd",
  "whisper-1",
  "gpt-3.5-turbo-1106",
  "gpt-3.5-turbo-instruct",
  "gpt-4o-mini-2024-07-18",
  "gpt-4o-mini",
  "tts-1",
  "tts-1-1106",
  "gpt-3.5-turbo-instruct-0914",
] as const;

export type OpenAIModel = (typeof OPEN_AI_MODELS)[number];

Description:option param Please get it from the corresponding platform.

TencentEnginOption

export interface TencentEngineOption extends BaseEngineOption {
  secretId: string;
  secretKey: string;
  region?: string;
}

Description: Option Param Please obtain it from the corresponding platform.

  • Related documentation:https://console.cloud.tencent.com/cam/capi

  • Region Configuration table

    地域 取值
    亚太东南(曼谷) ap-bangkok
    华北地区(北京) ap-beijing
    西南地区(成都) ap-chengdu
    西南地区(重庆) ap-chongqing
    华南地区(广州) ap-guangzhou
    港澳台地区(中国香港) ap-hongkong
    亚太东北(首尔) ap-seoul
    华东地区(上海) ap-shanghai
    华东地区(上海金融) ap-shanghai-fsi
    华南地区(深圳金融) ap-shenzhen-fsi
    亚太东南(新加坡) ap-singapore
    亚太东北(东京) ap-tokyo
    欧洲地区(法兰克福) eu-frankfurt
    美国东部(弗吉尼亚) na-ashburn
    美国西部(硅谷) na-siliconvalley

🤝 Contribute

Special attention: Please create a new branch based on the master, develop on the new branch, and create PR to Master after development.

  • Installation dependence

    pnpm install
  • Add new Engine

    • Add a new platform ENGINE plugin

      export interface XXEngineOption extends BaseEngineOption {
        key: string;
      }
      
      export function xx(options: XXEngineOption): Engine {
        const { key } = options;
        const base = "https://translate.yandex.net/api/v1.5/tr.json/translate";
        return {
          name: "yandex",
          async checkLanguage<T extends Engines>(text: string): Promise<string> {
            //TODO: This can be done with translate, in which case the target language configuration is reused.
          },
          async translate<T extends Engines>(text: string | string[], opts: EngineTranslateOptions<T>) {
            const { from, to } = opts;
            if (!Array.isArray(text)) {
              text = [text];
            }
            //TODO: Call the platform translation APIplatform translation API
            const translations: string[] = [];
            //TODO: Analyze the corresponding results of the platform API, and resolve the results to the translations back
            for (const translation of body.text) {
              if (translation) {
                translations.push(translation);
              }
            }
            return translations;
          },
        };
      }
    • Add the plugin to Engines(Location:/src/engines/index.ts)

      import { xx } from "./xx";
      export const engines = {
        google,
        azure,
        amazon,
        baidu,
        deepl,
        openai,
        xx,
      } as const;
    • Add the origin language configuration supported by the engine

      //Note: If the origin and target languages are the same, you can directly use the target language to configure them, otherwise please configure them separately
      //src/language/origin/index.ts
      import azure from "../target/azure";
      ...
      import xxx from "../target/xxx"
      
      export const originLanguages = {
        azure: azure,
        ...
        xxx: xxx,
      } as const;
      
      export type originLanguageMapNames = {
        amazon: keyof typeof amazon;
        ...
        xxx: keyof typeof xxx;
      };
      
      export type originLanguageMapValues = {
        amazon: ValuesOf<typeof amazon>;
        ...
        xxx: ValuesOf<typeof xxx>;
      };
    • Add the target language that is supported by the engine

      //src/language/target/index.ts
      import azure from "./azure";
      ...
      import xxx from "./amazon";
      
      export const targetLanguages = {
        azure: azure,
        ...
        xxx: xxx,
      } as const;
      
      export type targetLanguageMapNames = {
        amazon: keyof typeof amazon;
        ...
        xxx: keyof typeof xxx;
      };
      
      export type targetLanguageMapValues = {
        amazon: ValuesOf<typeof amazon>;
        ...
        xxx: ValuesOf<typeof xxx>;
      };
  • Build

    pnpm build
  • Test

    pnpm test

Tips: At present, the library can be used normally. Welcome everyone to experience. If you have any questions and suggestions, you can mention the feedback to me.If you are interested, you are welcome to join, let us improve this tool together. Help to click star ⭐, let more people know this tool, thank you for everyone🙏

🌹 Thanks

Note:Thanks to franciscop/translate for giving me ideas for a quick implementation of this library, and also indirectly some of his code. Much appreciated.🙏

📄 License

Translate is released under the MIT license. See the LICENSE file.

About

🎉一个简单的翻译库,支持多翻译引擎。A simple translation library that supports multiple translation engines

Topics

Resources

License

Stars

19 stars

Watchers

1 watching

Forks

Sponsor this project

 

Packages

 
 
 

Contributors