Giter Site home page Giter Site logo

leolabs / json-autotranslate Goto Github PK

View Code? Open in Web Editor NEW
125.0 5.0 36.0 356 KB

Translate a folder of JSON files containing translations into multiple languages.

License: MIT License

TypeScript 68.32% JavaScript 31.68%
localization translation i18n i18next icu google-translate deepl azure-translator

json-autotranslate's Introduction

json-autotranslate

This tool allows you to translate a locale folder containing multiple JSON files into multiple languages using Google Translate, DeepL (free/pro), Azure Translator, Amazon Translate, or manually. You can either use the translation keys (natural translation) or their values (key-based translation) as a source for translations.

If some of the strings have already been translated, they won't be translated again. This improves performance and ensures that you won't accidentally lose existing translations.

Interpolations (ICU: {name}, i18next: {{name}}, sprintf: %s) are replaced by placeholders (e.g. <0 />) before being passed to the translation service, so their structure doesn't get mangled by the translation.

Installation

$ yarn add json-autotranslate
# or
$ npm i -S json-autotranslate

Running json-autotranslate

$ yarn json-autotranslate
# or
$ npx json-autotranslate

Usage Examples

Translate natural language source files located in the locales directory using Google Translate and delete existing keys in translated JSON files that are no longer used.

$ yarn json-autotranslate -i locales -d -c service-account.json

Manually translate key-based source files located in the locales directory.

$ yarn json-autotranslate -i locales -s manual

Directory Structure

You can specify your locales/i18n directory structure using the --directory-structure option.

Default

locales
├── de
├── en
│   ├── login.json
│   └── register.json
├── fr
└── it

If you don't specify another source language, this tool will translate all files located in the en into all other languages that exist as directories. A single language directory (e.g. en) should only contain JSON files. Sub-directories and other files will be ignored.

Ngx-translate

i18n
├── de.json
├── en.json
├── fr.json
└── it.json

If you don't specify another source language, this tool will translate en.json into all other languages that exist as files. The i18n directory should only contain JSON files. Sub-directories and other files will be ignored.

File Structure

There are two ways that json-autotranslate can interpret files:

  • Natural Language (natural)
  • Key-Based (key-based)

If you don't specify a file structure type, json-autotranslate will automatically determine the type on a per-file basis. In most cases, this is sufficient.

Natural Language

This is the default way that this tool will interpret your source files. The keys will be used as the basis of translations. If one or more of the values in your source files don't match their respective key, you'll see a warning as this could indicate an inconsistency in your translations. You can fix those inconsistencies by passing the --fix-inconsistencies flag.

{
  "Your username doesn't exist.": "Your username doesn't exist.",
  "{email} is not a valid email address.": "{email} is not a valid email address."
}

Key-Based

If you pass use the key-based option (--type key-based), this tool will use the source file's values as the basis of translations. Keys can be nested, the structure will be transferred over to the translated files as well.

{
  "ERRORS": {
    "USERNAME": "Your username doesn't exist.",
    "EMAIL": "{email} is not a valid email address."
  },
  "LOGIN": "Login",
  "FORGOT_PASSWORD": "Forgot password?"
}

Available Services

As of this release, json-autotranslate offers five services:

  • google-translate (default, uses Google Translate to translate strings)
  • deepl (uses DeepL Pro to translate strings)
  • deepl-free (uses DeepL Free to translate strings)
  • azure (uses Azure's Translator Text to translate strings)
  • amazon-translate (uses Amazon Translate to translate strings)
  • manual (allows you to translate strings manually by entering them into the CLI)
  • dry-run (outputs a list of strings that will be translated without touching any files)

You can select a service using the -s or --service option. If you specify the --list-services flag, json-autotranslate will output a list of all available services.

Google Translate

To use this tool with Google Translate, you need to obtain valid credentials from Google. Follow these steps to get them:

  1. Select or create a Cloud Platform project
  2. Enable billing for your project (optional, I think)
  3. Enable the Google Cloud Translation API
  4. Set up authentication with a service account so you can access the API from your local workstation

You can specify the location of your downloaded JSON key file using the -c or --config option.

DeepL

To use this tool with DeepL, you need to obtain an API key from their website. If you don't have a Developer account yet, you can create one here.

DeepL Pro charges a fixed monthly price plus a variable fee for every 500 translated characters.

DeepL Free is limited to 500,000 characters translated per month.

After you have completed your sign-up, you can pass the API key to json-autotranslate using the -c or --config option.

The value of the --config argument is a comma separated string with the following: appKey,formality,batchSize.

The formality argument currently only works for target languages "DE" (German), "FR" (French), "IT" (Italian), "ES" (Spanish), "NL" (Dutch), "PL" (Polish), "PT-PT", "PT-BR" (Portuguese) and "RU" (Russian). Possible options are:

  • "default" (default)
  • "more" - for a more formal language
  • "less" - for a more informal language

To improve performance and prevent DeepL rate-limiting json-autotranslate batches multiple tokens into a single translation request. By default, the batchSize is set to 1000, meaning that 1000 tokens are translated at once. This can be controlled by adjusting the value in the --config parameter. This value was chosen because the DeepL prevents the body of a request to be larger than `128 KiB (128 · 1024 bytes)``. Based on experimentation, even with long tokens, this limit is not reached.

Reference

Azure Translator Text

To use this tool with Azure's Translator Text, you need to obtain an API key from their website. Sign Up for an Azure account if you don't have one already and create a new translator instance. You'll get an API key soon after that which you can pass to json-autotranslate using the -c or --config flag.

Unless you configure a global translator instance you will need to provide a region by adding it to the config string after the API key, separated by a comma: --config apiKey,region. As of this version, the following regions are available:

australiaeast, brazilsouth, canadacentral, centralindia, centralus, centraluseuap, eastasia, eastus, eastus2, francecentral, japaneast, japanwest, koreacentral, northcentralus, northeurope, southcentralus, southeastasia, uksouth, westcentralus, westeurope, westus, westus2, and southafricanorth

Reference

As of now, the first 2M characters of translation per month are free. After that you'll have to pay $10 per 1M characters that you translate. See their pricing

Amazon Translate

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "comprehend:DetectDominantLanguage",
                "translate:TranslateText"
            ],
            "Resource": "*"
        }
    ]
}
  • Configure your AWS user credentials locally, or wherever you will be running json-autotranslate. There are many ways to do this, but it is best to use something like shared credentials. Hard coded credentials should not be used for anything beyond proof of concept.
  • Create a json configuration file that defines the AWS region you want to use Translate in.

You can provide a path to the json configuration file via the --config flag. You may define any properties from TranslateClientConfig and they will be passed as the first argument to the Translate Constructor. At a minimum, this must include the AWS region.

Amazon Translate offers a free tier, but is paid after that. See their pricing page for details.

Manual

This service doesn't require any configuration. You will be prompted to translate the source strings manually in the console.

Available Matchers

Matchers are used to replace interpolations with placeholders before they are sent to the translation service. This ensures that interpolations don't get scrambled in the process. As of this release, json-autotranslate offers four matchers for different styles of interpolation:

  • icu (default, matches ICU MessageFormat interpolations)
  • i18next (matches i18next interpolations)
  • sprintf (matches sprintf-style interpolations like %s)
  • none (doesn't match any interpolations)

You can select a matchers using the -m or --matcher option. If you specify the --list-matchers flag, json-autotranslate will output a list of all available matchers.

Available Options

Options:
  -i, --input <inputDir>                        the directory containing language directories (default: ".")
  -l, --source-language <sourceLang>            specify the source language (default: "en")
  -t, --type <key-based|natural|auto>           specify the file structure type (default: "auto")
  -s, --service <service>                       selects the service to be used for translation (default: "google-translate")
  --list-services                               outputs a list of available services
  -m, --matcher <matcher>                       selects the matcher to be used for interpolations (default: "icu")
  -a, --with-arrays                             enables support for arrays in files, but removes support for keys named 0, 1, 2, etc.
  --list-matchers                               outputs a list of available matchers
  -c, --config <value>                          supply a config parameter (e.g. path to key file) to the translation service
  -f, --fix-inconsistencies                     automatically fixes inconsistent key-value pairs by setting the value to the key
  -d, --delete-unused-strings                   deletes strings in translation files that don't exist in the template
  -h, --help                                    output usage information
  --directory-structure <default|ngx-translate> the locale directory structure (default: "default")
  --decode-escapes                              decodes escaped HTML entities like &#39; into normal UTF-8 characters

Contributing

If you'd like to contribute to this project, please feel free to open a pull request.

json-autotranslate's People

Contributors

bilipp avatar bobmccracken avatar digitalcoyote avatar fkirc avatar georgegriff avatar gorbypark avatar idaapayo avatar leolabs avatar lucas-sellari avatar marc-on-github avatar neolegends avatar onionhammer avatar paulxuca avatar pierreandreis avatar sr258 avatar stefan-lacatus avatar steventilator avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

json-autotranslate's Issues

How to pass Google Translate API key in --config

I'm running the command: npx json-autotranslate --type keybased --matcher i18next --input locales --config locales/key.json

and I'm getting an error: "key must be a string, a buffer or an object". I have API key from Google Cloud and I don't know how to pass it to json-autotranslate. How my config JSON file should look like?

issue with type of json with azure

messages.zip
helper-messages.zip

Found 1 target language(s):
-> es

🏭 Loading source files...
├── helper-messages.json (key-based)
├── messages.json (key-based)
└── Done

✨ Initializing Azure...
└── Done

🔍 Looking for key-value inconsistencies in source files...
└── No inconsistencies found

🔍 Looking for invalid keys in source files...
└── No invalid keys found

💬 Translating strings from en to es...
├── Translating helper-messages.json (+84)
├── Translating messages.json
An error has occurred:
input.match is not a function
TypeError: input.match is not a function
	at exports.matchI18Next (/root/json-autotranslate/node_modules/json-autotranslate/lib/matchers/i18next.js:5:25)
	at Object.exports.replaceInterpolations (/root/json-autotranslate/node_modules/json-autotranslate/lib/matchers/index.js:20:24)
	at /root/json-autotranslate/node_modules/json-autotranslate/lib/services/azure-translator.js:107:49
	at Array.map (<anonymous>)
	at AzureTranslator.<anonymous> (/root/json-autotranslate/node_modules/json-autotranslate/lib/services/azure-translator.js:105:45)
	at step (/root/json-autotranslate/node_modules/json-autotranslate/lib/services/azure-translator.js:33:23)
	at Object.next (/root/json-autotranslate/node_modules/json-autotranslate/lib/services/azure-translator.js:14:53)
	at /root/json-autotranslate/node_modules/json-autotranslate/lib/services/azure-translator.js:8:71
	at new Promise (<anonymous>)
	at __awaiter (/root/json-autotranslate/node_modules/json-autotranslate/lib/services/azure-translator.js:4:12)

Stop automatically updating translations

I would like to know if there's a way to avoid translation updates as I am having the following issue. I have the texts back in a button which is translated by Google to dutch as rug, but I actually want terug. When I make the correction directly to the nl.json file and call json-autotranslate again I see rug is back.

Note I haven't changed the original text, I have only changed the dutch translation.

Throws error with double-brackets "{{" "}}" in json

I need to translate strings with {{ }}, which is a nesting variable symbol of the popular i18next library. Here is an example.

"KEY": "Words {{var1}} words {{var2}}",

While single { } works just fine, {{ }} throws below error

💬 Translating strings from en to ar...
├── Translating common.json (1 changes from cache)
An error has occurred:
Expected identifier but "{" found.
SyntaxError: Expected identifier but "{" found.
    at peg$buildStructuredError (/Users/ipadtinkamo/Documents/Tinkamo/tinkamo-mono/node_modules/messageformat-parser/parser.js:407:12)
    at Object.peg$parse [as parse] (/Users/ipadtinkamo/Documents/Tinkamo/tinkamo-mono/node_modules/messageformat-parser/parser.js:1978:11)
    at exports.matchIcu (/Users/ipadtinkamo/Documents/Tinkamo/tinkamo-mono/node_modules/json-autotranslate/lib/matchers/icu.js:6:40)
    at Object.exports.replaceInterpolations (/Users/ipadtinkamo/Documents/Tinkamo/tinkamo-mono/node_modules/json-autotranslate/lib/matchers/index.js:20:24)
    at GoogleTranslate.<anonymous> (/Users/ipadtinkamo/Documents/Tinkamo/tinkamo-mono/node_modules/json-autotranslate/lib/services/google-translate.js:113:57)
    at step (/Users/ipadtinkamo/Documents/Tinkamo/tinkamo-mono/node_modules/json-autotranslate/lib/services/google-translate.js:33:23)
    at Object.next (/Users/ipadtinkamo/Documents/Tinkamo/tinkamo-mono/node_modules/json-autotranslate/lib/services/google-translate.js:14:53)
    at /Users/ipadtinkamo/Documents/Tinkamo/tinkamo-mono/node_modules/json-autotranslate/lib/services/google-translate.js:8:71
    at new Promise (<anonymous>)
    at __awaiter (/Users/ipadtinkamo/Documents/Tinkamo/tinkamo-mono/node_modules/json-autotranslate/lib/services/google-translate.js:4:12)

I have to manually replace {{ }} to << >> and reverse it before / after using json-autotranslate. Please fix it if possible. Thx!

Rate Limit Exceeded

Problem:
Google-translate service reaches the rate limit, and translation fails with the following error:

An error has occurred:
User Rate Limit Exceeded
Error: User Rate Limit Exceeded

How to add a delay between translation calls or retry the translation call to google service after some period in case the rate limit is reached?

zh-CN and zh-TW are not supported

Google Translate service doesn't support Chinese. It seems it's connected with the letter case.

Found 108 target language(s):
-> af, am, ar, az, be, bg, bn, bs, ca, ceb, co, cs, cy, da, de, el, eo, es, et, eu, fa, fi, fr, fy, ga, gd, gl, gu, ha, haw, he, hi, hmn, hr, ht, hu, hy, id, ig, is, it, ja, jw, ka, kk, km, kn, ko, ku, ky, la, lb, lo, lt, lv, mg, mi, mk, ml, mn, mr, ms, mt, my, ne, nl, no, ny, or, pa, pl, ps, pt, ro, ru, rw, sd, si, sk, sl, sm, sn, so, sq, sr, st, su, sv, sw, ta, te, tg, th, tk, tl, tr, tt, ug, uk, ur, uz, vi, xh, yi, yo, zh-CN, zh-TW, zu

✨ Initializing Google Translate...

...

  { code: 'zh-CN', name: 'Chinese (Simplified)' },
  { code: 'zh-TW', name: 'Chinese (Traditional)' },

...

🙈 Google Translate doesn't support zh-CN. Skipping this language.
🙈 Google Translate doesn't support zh-TW. Skipping this language.

During debugging I found that supportedLanguages from the service contains zh-cn, zh-tw in lowercase.

private supportedLanguages: string[] = [];

Investigate starting from a grammatically complex language to improve pronoun translation precision

If we have partial strings such as "Registered on {date}" it might be important to know what the argument is in order to select the correct pronoun in other languages. English, however, is a very simple language that doesn't cover the different cases in other languages, so on the part of the translator there is a lot of guess work involved.

Perhaps if we start from a more complex language by default (such as german, french or spanish), we might get better translations.

Variable placeholders getting corrupted while using Google translate API

@leolabs Thanks for building this. This is a fantastic tool with excellent documentation and made my life a lot easier.

But I did face an issue while using this tool.

So I was trying to translate the strings without arabic translations in the following for fixing zulip/zulip#18933.

https://github.com/zulip/zulip/blob/05352f417a8f163ee8bda1fc1593875c432c5297/locale/ar/translations.json.

npx json-autotranslate -t natural --matcher icu -d -i locale -c google-key.json

The command completed sucesfully. But 17 strings ended up having the variable names corrupted. There are 55 strings with a variables in the file. So around 30% of the strings ended up being corrupted. I guess the good news is 70% got translated correctly :)

Here are the list of strings that were corrupted. The first line contains the string in English and the second line contains the translation in Arabic.


```bash
Are you sure you want to mention all <strong>__count__</strong> people in this stream? <br> This will send email and mobile push notifications to most of those <strong>__count__</strong> users. <br> If you don't want to do that, please edit your message to remove the <strong>@__mention__</strong> mention.
هل تريد بالتأكيد ذكر جميع <strong>__count__ من</strong> الأشخاص في مجموعة البث هذه؟<br>سيؤدي هذا إلى إرسال إشعارات عبر البريد الإلكتروني والجوال إلى معظم هؤلاء <strong>__العدد__ من</strong> المستخدمين.<br>إذا كنت لا تريد القيام بذلك ، يرجى تعديل رسالتك <strong>لإزالة__mention__</strong> الإشارة.

Message __- recipient_names__
الرسالة __- أسماء المستلمين__

Narrow to stream &quot;__display_recipient__&quot;
ضيق للدفق & quot؛ __ display_recipient __ & quot؛

Narrow to stream &quot;__display_recipient__&quot;, topic &quot;__topic__&quot;
ضيق للدفق & quot؛ __ display_recipient __ & quot ؛، موضوع & quot؛ __ موضوع __ & quot؛

Narrow to your private messages with __display_reply_to__
تضييق نطاق رسائلك الخاصة باستخدام __عرض_الرد على_تو__

Organization using __percent_used__% of __upload_quota__.
منظمة تستخدم __percent_used __٪ من __upload_quota__.

Owner: __name__
اسم المالك__

This organization is configured to restrict editing of message content to __minutes_to_edit__ minutes after it is sent.
تم تكوين هذه المؤسسة لتقييد تحرير محتوى الرسالة بـ __دقائق_لتحرير__ دقائق بعد إرسالها.

You (click to remove) reacted with __- emoji_name__
لقد (انقر للإزالة) تفاعلت بـ __- اسم_إيموجي__

You and __display_reply_to__
أنت و __عرض_الرد على_إلى__

You and __recipients__
أنت و __المستلمون_

You are not subscribed to stream __stream__
أنت غير مشترك في البث __ Stream__

You subscribed to stream __stream__
لقد اشتركت في البث __ Stream__

You unsubscribed from stream __stream__
لقد ألغيت اشتراكك في تيار __ Stream__

__- username__ reacted with __- emoji_name__
__- اسم المستخدم__ تفاعل بـ __- اسم_إيموجي__

__starred_status__ this message
__ starred_status__ هذه الرسالة

private messages with __- recipient__
رسائل خاصة مع __- المستلم__

Any idea why this happened?

Google translate | losing interpolations

Hey @leolabs !

Nice library and thanks for this!
I noticed that upon translating with i18-next format & using google-translate service, the interpolations at the end were not added back after the translation and this is because Google service translates <0 /> <1 /> etc to: &lt; 0 &gt; so you are not able to correcty replace them back again. I assume this is probably due to invalid html nodes? Maybe this change to the service happened later on.

I tested it locally and seems to work if you just change the xmlStyleReplacer to <br className="${index}" /> for example.

export const xmlStyleReplacer = (index: number) => `<${index} />`;

Cheers!

Translations written to en.json

So far json-autotranslate has always worked fine for me. I now suddenly get a weird error: When I run it, it translated as expected but all changes are written into en.json and not the actual locales.

I start it like this:
json-autotranslate -d --directory-structure ngx-translate -c google_translate.json -s google-translate --decode-escapes -t key-based -i locales/lumi -m i18next

The logs show that the direction is fine:
💬 Translating strings from en to de... (66 changes from cache)Lower case: en

But all the German strings are written to the en.json file.

I use version 1.9.0.

Some dependencies should be devDependencies

I have json-autotranslate in the devDependencies of my project and when I install my project I get a deprecation warning from tslint. That's why I've checked where it's from and it's a dependency of json-autotranslate. The dependencies referenced in package.json could be cleaned up so that the dependencies only include those that are really required on runtime (so that they aren't added to other projects on install).

From the looks of it, you might be able to move these dependencies to devDependencies:

  • @types/node
  • dotenv
  • ts-node
  • tslint
  • typescript

Support for DeepL Free API

Hi,

it looks like only the Pro DeepL version is supported, since the API request is made to the PRO endpoint. Could you add a parameter to support the free version as well (without Pro you have 500'000 characters/month).

Example to get all languages: https://api-free.deepl.com/v2/languages instead of https://api.deepl.com/v2/languages

const API_ENDPOINT = 'https://api.deepl.com/v2';

Google Translator oddities

When using the tool with Google Translator and i18next interpolation (using {{placeholder}}), there are cases in which google translate put strings into the 0 tag passed to Google Translate.

Example: Google translate returns
Det uppstod ett fel när filen <span>0 skulle</span> raderas från innehållsobjektet.
instead of

Det uppstod ett fel när filen <span>0</span> raderas från innehållsobjektet.

It looks like the translator tries to make sense of the sentence by putting in words inside the span. You can prevent this behavior by adding a translate="no" atribute to the span like this in src/matchers/index.ts:

export const xmlStyleReplacer = (index: number) => `<span translate="no">${index}</span>`;

I haven't submitted a PR on this, as I'm unsure if this will break other translators. Maybe you need a Google Translate specific replacer...

Another thing I've noticed is that Google Translate escapes all characters considered unsafe in HTML. So an apostrophe become '. It would be great if the json-autotranslate decodes these characters back to their actual value. It might be worth adding an option for this, as source strings might already contain HTML encoded characters.

Release new version

Hi, great tool! I was a bit confused at first that the NPM version isn't the same as the master on GitHub. It would be great if you could release a new version!

Better ICU handling

Hey me again!

I've found a few issues with the mechanism of using placeholders in html and icu syntax, specifically the plural stuff i added, but it could effect other things.

I have a solution, but i may not be able to contribute it any time soon, partly because it would require a large-ish change to how matching/replacing works for ICU strings that might not be wanted for this library. I thought I would at least open this issue to demonstrate how the AST parsing can be achieved.

The problem

(I'm aware this is a bad translation string but it shows the problem well)

Input: "defaultMessage": "Select all {totalRows, select, undefined {available} other {{totalRows}}} rows"

Google: "defaultMessage": "Sélectionnez toutes {totalRows, select, undefined { lignes } other {{totalRows}}} disponibles"
Aws: "defaultMessage": "Toutes les} other {{totalRows}}} lignes{totalRows, select, undefined { disponibles sont sélectionnées."

Why does this happen?

Because the translation services decides to move the html around, to make the sentence better in other langs
(i've put this back into english to demonstrate the issue)

All <span translate="no">1</span><span translate="no">0</span>available rows
selected.

So it appears you can't always guarantee the ordering of html placeholders once its been the through the translator.

I appreciate that this was a feature that I contributed and it doesn't quite hit all the cases, so sorry for that.

A solution

To solve this the library could parse the ast in a different way, and translate the specific values which should translate, i've done this here for google and amazon

https://github.com/leolabs/json-autotranslate/compare/master...Georgegriff:json-autotranslate:icu-parsing?expand=1#diff-b15d6586b5ec27fb11a3ca41ba1fa178626842745da09f66554ed7058eec840e

I had to introduce a new concept, Matchers api wont work, which is why i'm not jumping to a contribution here. I also haven't fixed up other translation services

This may or may not turn into a PR, your call, but I thought I would at least document a solution in case it's helpful in the future

Code detail

  • I swapped out the ast parser for more friendly one to TS and one which has nice helpers.
  • the "core" of whats going on here is this recursive function.
import {
  isLiteralElement,
  isTagElement,
  isPluralElement,
  isSelectElement,
} from '@formatjs/icu-messageformat-parser';
async function doTranslateAst(
  messageElements: MessageFormatElement[],
  translateText,
): Promise<MessageFormatElement[]> {
  const translatedElements = await Promise.all(
    messageElements.map(async (messageElement) => {
      if (isLiteralElement(messageElement)) {
        const originalValue = messageElement.value;
        // some services don't play well with whitespace, they remove it, manually handle that.
        const trimmedValue = originalValue.trim();
        const startingWhitespace =
          originalValue[0] !== trimmedValue[0] ? originalValue[0] : '';
        const endingWhitespace =
          originalValue[originalValue.length - 1] !==
          trimmedValue[trimmedValue.length - 1]
            ? originalValue[originalValue.length - 1]
            : '';
        messageElement.value = `${startingWhitespace}${await translateText(
          trimmedValue,
        )}${endingWhitespace}`;
      }

      if (isPluralElement(messageElement) || isSelectElement(messageElement)) {
        const optionEntries = await Promise.all(
          Object.keys(messageElement.options).map(async (id) => {
            const pluralChildElement = messageElement.options[id];
            const value = await doTranslateAst(
              pluralChildElement.value,
              translateText,
            );
            pluralChildElement.value = value;

            return [id, pluralChildElement];
          }),
        );
        messageElement.options = Object.fromEntries(optionEntries);
      }

      if (isTagElement(messageElement)) {
        const elementChildren = await doTranslateAst(
          messageElement.children,
          translateText,
        );
        messageElement.children = elementChildren;
      }

      return messageElement;
    }),
  );

  return translatedElements;
}
import { printAST } from '@formatjs/icu-messageformat-parser/printer';
import {
  parse,
} from '@formatjs/icu-messageformat-parser';
nst astMessageElements = parse(input);
  const translatedMessaged = await doTranslateAst(
    astMessageElements,
    translateText,
  );
  // convert back to string
  return printAST(translatedMessaged);

Here is a good way of playing with the AST's

image

Windows file formats UTF-8-BOM (CR LF)

Ran into an issue running json-autotranslate for the second time on Windows platform. It appears that when reading the files from the cache folder an exception will be thrown parsing JSON if the files are not UTF-8 with Unix (LF) EOL. In my case one of the files was UTF-8-BOM with Windows (CR LF) EOL, I assume that the file format is carried over from the original file. (I happen to auto generate one of the json files from a RESX file hence one file was in a windows file format).

To fix the problem I manually converted the JSON files to UTF-8 with Unix (LF) EOL, including those in the cache folder.

Adding a note about Windows compatibility would be sufficient, or even better adding support for windows file formats.

Thanks for the great work!

Version 1.5.2

Unexpected token  in JSON at position 0
SyntaxError: Unexpected token  in JSON at position 0
    at JSON.parse (<anonymous>)
    at D:\repos\project\node_modules\json-autotranslate\lib\index.js:248:91

Curly brackets inside JSON value throw an error

Hello,

when I run auto-translate on a JSON file that has this record in it:

"LABEL_SEQUENCE_STEP": "Step {value:step}",

it will throw this error:

An error has occured:
Expected "," or "}" but ":" found.
SyntaxError: Expected "," or "}" but ":" found.
    at peg$buildStructuredError (/Users/petrchutny/Tinkamo/Tinkamo App – All/node_modules/messageformat-parser/parser.js:407:12)
    at Object.peg$parse [as parse] (/Users/petrchutny/Tinkamo/Tinkamo App – All/node_modules/messageformat-parser/parser.js:1978:
11)
    at exports.matchIcu (/Users/petrchutny/Tinkamo/Tinkamo App – All/node_modules/json-autotranslate/lib/matchers/icu.js:5:40)
    at Object.exports.replaceInterpolations (/Users/petrchutny/Tinkamo/Tinkamo App – All/node_modules/json-autotranslate/lib/matc
hers/index.js:17:24)

    at GoogleTranslate.<anonymous> (/Users/petrchutny/Tinkamo/Tinkamo App – All/node_modules/json-autotranslate/lib/services/goog
le-translate.js:78:57)
    at step (/Users/petrchutny/Tinkamo/Tinkamo App – All/node_modules/json-autotranslate/lib/services/google-translate.js:32:23)
    at Object.next (/Users/petrchutny/Tinkamo/Tinkamo App – All/node_modules/json-autotranslate/lib/services/google-translate.js:
13:53)
    at /Users/petrchutny/Tinkamo/Tinkamo App – All/node_modules/json-autotranslate/lib/services/google-translate.js:7:71
    at new Promise (<anonymous>)
    at __awaiter (/Users/petrchutny/Tinkamo/Tinkamo App – All/node_modules/json-autotranslate/lib/services/google-translate.js:3:
12)

When I remove the curly brackets from inside the double quotes, everything is OK.
Trying to escape curly brackets with \ doesn't work (like this: "LABEL_SEQUENCE_STEP": "Step \{value:step\}"
I previously thought it's caused only by curly brackets, but it seems it's the combination of them and the colon ':' in between them, because there is also this record, which doesn't throw any error: "MSG_CONNECTED": "{name}<br>is connected",

Error empty other language directory

When I tried to use it with:

json-autotranslate -i locales --config google_key.json -s google-translate

and I let the fr and de language directories empty I had the following error:

An error has occurred:
Cannot read property 'name' of undefined
TypeError: Cannot read property 'name' of undefined
at /Users/catalin/node_modules/json-autotranslate/lib/index.js:390:141
at step (/Users/catalin/node_modules/json-autotranslate/lib/index.js:68:23)
at Object.next (/Users/catalin/node_modules/json-autotranslate/lib/index.js:49:53)
at fulfilled (/Users/catalin/node_modules/json-autotranslate/lib/index.js:40:58)
at runMicrotasks ()
at processTicksAndRejections (internal/process/task_queues.js:95:5)

Cannot read properties of undefined (reading 'name')

As per the package instructions, we just need to create the language folder and this package will create translation files in the folder.

I used this command:

npx json-autotranslate -i public/locales -m i18next -c gcloud_sa.json -d

error log:

💬 Translating strings from en to de...
├── Translating common.json (0 changes from cache)
An error has occurred:
Cannot read properties of undefined (reading 'name')
TypeError: Cannot read properties of undefined (reading 'name')
    at /Users/captain/Desktop/saiberio/repos/saiberio/node_modules/json-autotranslate/lib/index.js:390:141
    at step (/Users/captain/Desktop/saiberio/repos/saiberio/node_modules/json-autotranslate/lib/index.js:68:23)
    at Object.next (/Users/captain/Desktop/saiberio/repos/saiberio/node_modules/json-autotranslate/lib/index.js:49:53)
    at fulfilled (/Users/captain/Desktop/saiberio/repos/saiberio/node_modules/json-autotranslate/lib/index.js:40:58)
    at processTicksAndRejections (node:internal/process/task_queues:96:5)

If I create the placeholder JSON files inside the language folder, with an empty JSON ({}), it creates the translations successfully.

Any ideas why I see this behavior?

When files do not exist in 'destination' language, vague error is thrown

Line 388 here will error with a vague '.name doesn't exist' error when I have a 'help.json' file in my 'en' directory, but 'help.json' does not exist in my de directory.

image

After looking through your source, I understood what was going on and made those files by hand, but a clearer error message might be helpful.

Thank you for the library! It's been very useful and saved me hours of my life. I hope you're well!

Some problem

After install i have some problem:

Снимок экрана 2020-04-27 в 23 08 07

Can you tell me what the problem is?

issue with google translate

npx json-autotranslate -i locales -s google-translate -c traducciones-352415-79659df1c6f1.json
Found 2 target language(s):
-> ar, de

🏭 Loading source files...
├── helper-messages.json (key-based)
├── messages.json (key-based)
└── Done

✨ Initializing Google Translate...
[
  { code: 'af', name: 'Afrikaans' },
  { code: 'sq', name: 'Albanian' },
  { code: 'am', name: 'Amharic' },
  { code: 'ar', name: 'Arabic' },
  { code: 'hy', name: 'Armenian' },
  { code: 'az', name: 'Azerbaijani' },
  { code: 'eu', name: 'Basque' },
  { code: 'be', name: 'Belarusian' },
  { code: 'bn', name: 'Bengali' },
  { code: 'bs', name: 'Bosnian' },
  { code: 'bg', name: 'Bulgarian' },
  { code: 'ca', name: 'Catalan' },
  { code: 'ceb', name: 'Cebuano' },
  { code: 'ny', name: 'Chichewa' },
  { code: 'zh-CN', name: 'Chinese (Simplified)' },
  { code: 'zh-TW', name: 'Chinese (Traditional)' },
  { code: 'co', name: 'Corsican' },
  { code: 'hr', name: 'Croatian' },
  { code: 'cs', name: 'Czech' },
  { code: 'da', name: 'Danish' },
  { code: 'nl', name: 'Dutch' },
  { code: 'en', name: 'English' },
  { code: 'eo', name: 'Esperanto' },
  { code: 'et', name: 'Estonian' },
  { code: 'tl', name: 'Filipino' },
  { code: 'fi', name: 'Finnish' },
  { code: 'fr', name: 'French' },
  { code: 'fy', name: 'Frisian' },
  { code: 'gl', name: 'Galician' },
  { code: 'ka', name: 'Georgian' },
  { code: 'de', name: 'German' },
  { code: 'el', name: 'Greek' },
  { code: 'gu', name: 'Gujarati' },
  { code: 'ht', name: 'Haitian Creole' },
  { code: 'ha', name: 'Hausa' },
  { code: 'haw', name: 'Hawaiian' },
  { code: 'iw', name: 'Hebrew' },
  { code: 'hi', name: 'Hindi' },
  { code: 'hmn', name: 'Hmong' },
  { code: 'hu', name: 'Hungarian' },
  { code: 'is', name: 'Icelandic' },
  { code: 'ig', name: 'Igbo' },
  { code: 'id', name: 'Indonesian' },
  { code: 'ga', name: 'Irish' },
  { code: 'it', name: 'Italian' },
  { code: 'ja', name: 'Japanese' },
  { code: 'jw', name: 'Javanese' },
  { code: 'kn', name: 'Kannada' },
  { code: 'kk', name: 'Kazakh' },
  { code: 'km', name: 'Khmer' },
  { code: 'rw', name: 'Kinyarwanda' },
  { code: 'ko', name: 'Korean' },
  { code: 'ku', name: 'Kurdish (Kurmanji)' },
  { code: 'ky', name: 'Kyrgyz' },
  { code: 'lo', name: 'Lao' },
  { code: 'la', name: 'Latin' },
  { code: 'lv', name: 'Latvian' },
  { code: 'lt', name: 'Lithuanian' },
  { code: 'lb', name: 'Luxembourgish' },
  { code: 'mk', name: 'Macedonian' },
  { code: 'mg', name: 'Malagasy' },
  { code: 'ms', name: 'Malay' },
  { code: 'ml', name: 'Malayalam' },
  { code: 'mt', name: 'Maltese' },
  { code: 'mi', name: 'Maori' },
  { code: 'mr', name: 'Marathi' },
  { code: 'mn', name: 'Mongolian' },
  { code: 'my', name: 'Myanmar (Burmese)' },
  { code: 'ne', name: 'Nepali' },
  { code: 'no', name: 'Norwegian' },
  { code: 'or', name: 'Odia (Oriya)' },
  { code: 'ps', name: 'Pashto' },
  { code: 'fa', name: 'Persian' },
  { code: 'pl', name: 'Polish' },
  { code: 'pt', name: 'Portuguese' },
  { code: 'pa', name: 'Punjabi' },
  { code: 'ro', name: 'Romanian' },
  { code: 'ru', name: 'Russian' },
  { code: 'sm', name: 'Samoan' },
  { code: 'gd', name: 'Scots Gaelic' },
  { code: 'sr', name: 'Serbian' },
  { code: 'st', name: 'Sesotho' },
  { code: 'sn', name: 'Shona' },
  { code: 'sd', name: 'Sindhi' },
  { code: 'si', name: 'Sinhala' },
  { code: 'sk', name: 'Slovak' },
  { code: 'sl', name: 'Slovenian' },
  { code: 'so', name: 'Somali' },
  { code: 'es', name: 'Spanish' },
  { code: 'su', name: 'Sundanese' },
  { code: 'sw', name: 'Swahili' },
  { code: 'sv', name: 'Swedish' },
  { code: 'tg', name: 'Tajik' },
  { code: 'ta', name: 'Tamil' },
  { code: 'tt', name: 'Tatar' },
  { code: 'te', name: 'Telugu' },
  { code: 'th', name: 'Thai' },
  { code: 'tr', name: 'Turkish' },
  { code: 'tk', name: 'Turkmen' },
  { code: 'uk', name: 'Ukrainian' },
  ... 11 more items
]
└── Done

🔍 Looking for key-value inconsistencies in source files...
└── No inconsistencies found

🔍 Looking for invalid keys in source files...
└── No invalid keys found

💬 Translating strings from en to ar...
├── Translating helper-messages.json (+84)
├── Translating messages.json
An error has occurred:
input.charCodeAt is not a function
TypeError: input.charCodeAt is not a function
    at peg$parseargument (/root/json-autotranslate/node_modules/messageformat-parser/parser.js:497:15)
    at peg$parsetoken (/root/json-autotranslate/node_modules/messageformat-parser/parser.js:431:10)
    at peg$parsestart (/root/json-autotranslate/node_modules/messageformat-parser/parser.js:419:10)
    at Object.peg$parse [as parse] (/root/json-autotranslate/node_modules/messageformat-parser/parser.js:1969:16)
    at exports.matchIcu (/root/json-autotranslate/node_modules/json-autotranslate/lib/matchers/icu.js:6:40)
    at Object.exports.replaceInterpolations (/root/json-autotranslate/node_modules/json-autotranslate/lib/matchers/index.js:20:24)
    at GoogleTranslate.<anonymous> (/root/json-autotranslate/node_modules/json-autotranslate/lib/services/google-translate.js:113:57)
    at step (/root/json-autotranslate/node_modules/json-autotranslate/lib/services/google-translate.js:33:23)
    at Object.next (/root/json-autotranslate/node_modules/json-autotranslate/lib/services/google-translate.js:14:53)
    at /root/json-autotranslate/node_modules/json-autotranslate/lib/services/google-translate.js:8:71

source json files here:

https://github.com/KnowageLabs/Knowage-Server/tree/master/knowage-vue/src/i18n/en_US

pls help me to solve this

Feature wanted: Add new languages not supported by Google Translate

Hi,

I want to tell you that json-autotranslate works like charm! I really enjoy it. Recently I have encountered a problem.

I already have my JSON translated into Quechua (Peru Spanish). But it keeps saying "Translation doesn't support pe. Skipping this language." Neither auto-translation nor manual works. I hope it can support languages out of Google Translate's scope. Once I have the folder and JSON ready, it can always use the local resource to translate.

Anyway, I want a walkaround.

Update cache with already translated key-value pairs

I'm migrating from intl to i18next and using json-autotranslate to add new translations. When i run script to generate new translations:

json-autotranslate -i public/locales -s manual --type keybased -l en

It asking for the already existing key-value pairs in all files (the cache is not updated, i think).

There is a way to update cache with already translated key-value pairs in all files?

Id like this feature because i add .json-autotranslate-cache/ to .gitignore and the idea is run something like 'json-autotranslate -updatecache' to verify and update the local cache before run the generate translations script.

i18next style string interpolation causes an error

If I have a string value that uses i18next interpolation, such as:

"I am {{author.name}}"

then I get the following error:

An error has occured:
Expected identifier but "{" found.
SyntaxError: Expected identifier but "{" found.

BTW, thanks for building this, it's super useful!

Questions

Sorry, I wasn't sure the best way to send you some questions about the library ...

  1. I'm seeing something where a phrase like "Hop Farm" does not get translated but "Hop farm" does get translated properly. I don't really have any proper nouns in my translation file. Is there any way to force the translation to always translate uppercase words?

  2. The word "hops" and "hop" is particularly troublesome. In my context I'm referring to the ingredient used in beer: lúpulo, hopfen, houblon. Aside from interpolation, is there a way to force the translator to prefer one translation of a word over another?

Feature suggestion: Translating updated strings again

Hello,

thanks for making this amazing script. It helps us greatly to save so much time translating at Tinkamo. I know this might be a big idea requiring more coding, but what do you think about the functionality of being able to detect whether a source string has changed and translating it again?
What do you think about it? :)

ICU Plurals Support fix

Hey, first off this project is straight up 🔥 I'm really hoping to be able leverage it to help kick off internationalisation with the product that I work on.

I notice this project does not currently support plurals for ICU e.g.

{value, plural, =0 {No unread messages} one {{value} unread message} other {{value} unread messages} }

I've given a shot at adding support in the fork below. Is this something you'd be interested in me opening a PR for?
Some of the code/types may need tidying up, happy to receive pointers once/if get to PR stage

https://github.com/leolabs/json-autotranslate/compare/master...Georgegriff:json-autotranslate:icu-plurals-support?expand=1

This change will mean that "No unread messages" "unread message" and "unread messages" would be sent to be translated instead of just all placeholdered

i18next plurals

Hi @leolabs, first, thank you for this wonderful library, it is really useful for projects that are translated into multiple languages. We are using plurals in our i18next project, something like this:

English:

    "Show older comments_one": "Show {{count}} older comment",
    "Show older comments_other": "Show {{count}} older comments",

Polish:

    "Show older comments_one": "Pokaż {{count}} starszy komentarz",
    "Show older comments_few": "Pokaż {{count}} starsze komentarze",
    "Show older comments_many": "Pokaż {{count}} starszych komentarzy",

As you can see, Polish has different plural forms. When I ran json-autotranslate with -d, it removed all these and added the key with _other as the last entry under the parent key. Is there a way to do it correctly for languages like this or this is something that's not implemented?

attranslate - A rewrite of json-autotranslate

First of all, thank you for writing json-autotranslate 👍
json-autotranslate worked great for all my i18next-projects 😎

Nevertheless, I came to the conclusion that a complete rewrite of json-autotranslate is appropriate.
The resulting rewrite is attranslate: https://github.com/fkirc/attranslate
attranslate addresses the following features that I was missing in JSON-autotranslate:

  • Do not enforce any specific folder-structure. Not every project uses a folder-structure that is prescribed by i18next.
  • Support additional file-formats other than JSON (XML, Plist, YAML, PO/POT).
  • Generate caches only for source-files, but not for target-files. This reduces noise in version-control.
  • Place a higher emphasis on file-stability, that is, only change a minimum number of lines.
  • Ensure quality with a comprehensive test-suite.
  • Optimize performance. For example, remove available-language-checks that were painful to keep up-to-date.
  • Make it simpler to add new services or new file-formats. For example, move matching-logic from individual services into the core-unit.

However, despite of all those differences, there is still a lot of duplication between attranslate and json-autotranslate.
This raises the question whether it is really necessary to maintain both codebases in the long-term.
Ideally, all maintenance effort would go into one codebase.
Please let me know whether you would be open to a collaboration instead of maintaining competing sub-projects.

Does not translate to French.

I ran command json-autotranslate -f -i locales -m i18next -c .\grand-store-292020-1d6d5dbdee41.json and this is what I got.
My french json has all keys but no values.

Found 1 target language(s):
-> fr

🏭 Loading source files...
├── translation.json (natural)
└── Done

🔍 Looking for key-value inconsistencies in source files...
└── No inconsistencies found

🔍 Looking for invalid keys in source files...
└── No invalid keys found

💬 Translating strings from en to fr...
├── Translating translation.json (0 changes from cache) (+0)
└── All strings have been translated.

🗂 Caching source translation files...
└── Translation files have been cached.

0 new translations have been added!

The source language en doesn't exist.

I'm having troubles running this.

When I run npx json-autotranslate

I get this error:

An error has occurred:
The source language en doesn't exist.
Error: The source language en doesn't exist.
    at /Users/xxx/Documents/dev/translate/node_modules/json-autotranslate/lib/index.js:129:31
    at step (/Users/xxx/Documents/dev/translate/node_modules/json-autotranslate/lib/index.js:68:23)
    at Object.next (/Users/xxx/Documents/dev/translate/node_modules/json-autotranslate/lib/index.js:49:53)
    at /Users/xxx/Documents/dev/translate/node_modules/json-autotranslate/lib/index.js:43:71
    at new Promise (<anonymous>)
    at __awaiter (/Users/xxx/Documents/dev/translate/node_modules/json-autotranslate/lib/index.js:39:12)
    at translate (/Users/xxx/Documents/dev/translate/node_modules/json-autotranslate/lib/index.js:115:12)
    at Object.<anonymous> (/Users/xxx/Documents/dev/translate/node_modules/json-autotranslate/lib/index.js:345:1)
    at Module._compile (node:internal/modules/cjs/loader:1103:14)
    at Object.Module._extensions..js (node:internal/modules/cjs/loader:1157:10)

I also get the same error when using yarn yarn json-autotranslate

% yarn json-autotranslate
yarn run v1.22.18
warning package.json: No license field
$ /Users/xxx/Documents/dev/translate/node_modules/.bin/json-autotranslate

An error has occurred:
The source language en doesn't exist.
Error: The source language en doesn't exist.
    at /Users/xxx/Documents/dev/translate/node_modules/json-autotranslate/lib/index.js:129:31
    at step (/Users/xxx/Documents/dev/translate/node_modules/json-autotranslate/lib/index.js:68:23)
    at Object.next (/Users/xxx/Documents/dev/translate/node_modules/json-autotranslate/lib/index.js:49:53)
    at /Users/xxx/Documents/dev/translate/node_modules/json-autotranslate/lib/index.js:43:71
    at new Promise (<anonymous>)
    at __awaiter (/Users/xxx/Documents/dev/translate/node_modules/json-autotranslate/lib/index.js:39:12)
    at translate (/Users/xxx/Documents/dev/translate/node_modules/json-autotranslate/lib/index.js:115:12)
    at Object.<anonymous> (/Users/xxx/Documents/dev/translate/node_modules/json-autotranslate/lib/index.js:345:1)
    at Module._compile (node:internal/modules/cjs/loader:1103:14)
    at Object.Module._extensions..js (node:internal/modules/cjs/loader:1157:10)

error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.

I'm trying to use it with deepl-free

can you please show me a command to make it run with deepl-free with translation files inside the locales directory en.default.json

Add command to change a key

Every so often I need to change the value of a key. Usually it's a better message or I need to completely change a label. Right now, if I make a change I update the English translation file then delete that key from 14 other language files. It's a bit tedious.

Would would be nice is the ability to re-translate just one key.

I don't want to regenerate all the translation files because I've made some manual changes and don't want to lose them.

Thanks for making this great tool!

Not all keys are translated

Thanks for an amazing tool!

The only problem I have is that not all keys are translated but available in en. In es for example, only 10/40 files are translated.

My command looks like this:
json-autotranslate -i src/locales -d -c service-account.json -m i18next -t natural -f

File structure:
Screenshot 2020-10-28 at 13 47 03

Example JSON:

{
  "description": "",
  "title": ""
}

source language en doesnt exist

I created the directory localed added subfolders of languages I want to translate en to, inside en folder I have my source json file that needs translating, I'm using deepl which I did signed up with

image

How to handle input keys with "." in names

I have some strings to translate which have the following structure:

{
  "path.to.Component.yourProgress": {
    "defaultMessage": "Your progress"
  },
}

I'm finding that by default the library is unflattening my object, i suspect because internally flattenjs uses the same character for splitting objects

example output ends up breaking my json input:

{
"path": {
  "to": {
    "Component": {
      "yourProgress": {
             "defaultMessage": "Your progress"
         }
    }
  }
}
}

Ideally the library wouldn't transform the JSON is there some way to fix this, or might have i have to flatten the files myself?

DeepL formality

Is it possible to add the formality parameter to the deepL API?

More information for this parameter find here

Sets whether the translated text should lean towards formal or informal language. This feature currently only works for target languages "DE" (German), "FR" (French), "IT" (Italian), "ES" (Spanish), "NL" (Dutch), "PL" (Polish), "PT-PT", "PT-BR" (Portuguese) and "RU" (Russian).Possible options are.

i18next - Interpolation throwing partial errors

@leolabs It seems there are some issues in supporting the interpolations. It's working well in some places but it's considering for translations at some other places. It's completely random. Find the example here.

I have a key: value like this -> "title": "{{underlying_asset}}-{{quoting_asset}} Index"

After converting it to Arabic, the result is: "title": "<span><span>0-1</span></span> مؤشر"

Ideally, it shouldn't ignore those keys underlying_asset, quoting_asset

Please add license file

Hi - thank you for this library. We want to use your library but our legal team requires a license file before they allow us to use a library. We would be grateful If you could please add a license file. Thank you.

i want use azure service

root@ubuntu21:~/json-autotranslate# npx json-autotranslate

An error has occurred:
The source language en doesn't exist.
Error: The source language en doesn't exist.
	at /root/json-autotranslate/node_modules/json-autotranslate/lib/index.js:129:31
	at step (/root/json-autotranslate/node_modules/json-autotranslate/lib/index.js:68:23)
	at Object.next (/root/json-autotranslate/node_modules/json-autotranslate/lib/index.js:49:53)
	at /root/json-autotranslate/node_modules/json-autotranslate/lib/index.js:43:71
	at new Promise (<anonymous>)
	at __awaiter (/root/json-autotranslate/node_modules/json-autotranslate/lib/index.js:39:12)
	at translate (/root/json-autotranslate/node_modules/json-autotranslate/lib/index.js:115:12)
	at Object.<anonymous> (/root/json-autotranslate/node_modules/json-autotranslate/lib/index.js:345:1)
	at Module._compile (node:internal/modules/cjs/loader:1105:14)
	at Object.Module._extensions..js (node:internal/modules/cjs/loader:1159:10)

how solve this?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.