Code Monkey home page Code Monkey logo

deepl-node's People

Contributors

daniel-jones-dev avatar deejaytc avatar ireadewolu avatar janebbing avatar mike-winters-deepl 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  avatar  avatar  avatar  avatar

deepl-node's Issues

Update axios to latest version

Version used by deepl-node has vulnerabilities and should be updated

  • moderate | Follow Redirects improperly handles URLs in the url.parse() function
  • Package | follow-redirects
  • Patched in | >=1.15.4
  • Dependency of | deepl-node
  • Path | deepl-node > axios > follow-redirects
  • More info | https://www.npmjs.com/advisories/1095374

Cloudflare workers support?

This library cannot be used in cloudflare workers because it depends on XMLHttpRequest.
Moreover, if I send requests manually they fail with status code 525.

Code to reproduce

const deepLUrl = 'https://api-free.deepl.com/v2/translate'
const text = 'I like my cat'
const to = 'de'
const from = 'en'

const resp = await fetch(deepLUrl, {
  method: 'POST',
  headers: {
    'Content-Type': 'application/x-www-form-urlencoded',
    Authorization: `DeepL-Auth-Key ${env.DEEPL}`,
  },
  body: `text=${encodeURIComponent(text)}&target_lang=${to.toUpperCase()}&source_lang=${from.toUpperCase()}`,
})
if (!resp.ok) throw new Error(`DeepL error (${resp.status}) ` + resp.statusText) // throws in workers
const response = await resp.json()
response.translations[0].text // works in node

This problem is often mentioned in cloudflare community (example). According to cloudflare "This is typically caused by a configuration issue in the origin web server".

Is there any hope for a fix? Cloudflare workers become more and more popular nowadays.

Wrong detection of source language

I need to detect source language of word "Insomnia". When i use deepl-node package, i got source language Slovak(sk). When i use Deepl on site translator i got, when i typed "Insomnia", English language detection.

autotranslate does not work

today autotranslate does not work, until yesterday it worked fine, today the language detected is the same as the target language

TypeError

We are found when we test to use deepl-node packages in our mobile app.
Package download link..
deepl-node - npm (npmjs.com)

Our app is based on react-native language.
We just use sample code and connection tests with deepl server.

Found err info:
[TypeError: Cannot read property 'prototype' of undefined]

Bug while using deepl-node

Hi , I have recently subscribed on Deepl Pro Advanced plan. I am trying to use deepl-node package: https://github.com/DeepLcom/deepl-node
However i get the following error : AuthorizationError: Authorization failure, check auth_key, message: Wrong endpoint. Use https://api.deepl.com
at checkStatusCode
I tried creating a new authentication key and I tried with it but no chance.I was wondering if you could help me, please?

remove supportsFormaility from getSourceLanguages call

Describe the bug
For all languages in the getSourceLanguages call an empty 'supportyFormality' field is returned, this should be omitted.

 { name: 'Bulgarian', code: 'bg', supportsFormality: undefined },
 { name: 'Czech', code: 'cs', supportsFormality: undefined },
 { name: 'Danish', code: 'da', supportsFormality: undefined },
 { name: 'German', code: 'de', supportsFormality: undefined },

To Reproduce
use translator.getSourceLanguages()

Expected behavior
undefined fields should be omited

Feature Request: Markdown Handling

Hi there, thanks for the great library to use the DeepL API!

I made a github action for using deepl-node to translate text documents, however there's quite a lot of limitations in trying to parse markdown elements.

You can refer to some limitations that's mentioned in this demo or this PR.

The formatting errors that were raised in both examples may be due to the use of markdown checkboxes, bolded text etc, since most other HTML elements were able to be translated accurately, and only break on certain languages.

Feature Idea: Translate webpage from url

The contributors file said that would-be contributors should open an issue for suggested features instead of just jumping straight into making a pull request. I'm using the bug template because there is no feature template.

Describe the Feature

Generate a translated HTML document based off of the URL for a webpage. The following code snippet would translate the page for DeepL's English Wikipedia article into German and save it in the file DeepLWiki.html:

await translator.translateWebpageToDocument(
        'https://en.wikipedia.org/wiki/DeepL_Translator',
        'DeepLWiki.html',
        'en',
        'de',
        { formality: 'more' },
    );

In line with the other document related functions, there can be an uploadWebpageToDocument function that takes a URL as the first argument with the rest of its arguments being the same as uploadDocument. getDocumentStatus and downloadDocument would not need their own versions as uploadWebpageToDocument would return a DocumentHandle like uploadDocument does.

Implementation

Without writing the exact code, I think uploadWebpageToDocument would first make a request to the URL that's passed in as an argument. If the request is successful and the response has it's Content-Type header set text/html, the response HTML gets put into a buffer and passed to uploadDocument along with the rest of the parameters. If the request to the website fails or the response is not the expected mime type, the function throws an error.

Increasing "socket hang up" errors when updated to 1.13

Describe the bug
Since we updated to version node-deepl to version 1.13.0, and follow-redirects 1.15.6 (because of a security update) we've seen an increasing number of errors of the type "socket hang up". We've never seen this error before.

image
node_modules/axios/dist/node/axios.cjs:836:14 in AxiosError.from
node_modules/axios/dist/node/axios.cjs:3086:25 in RedirectableRequest.handleRequestError
node:events:539:35 in RedirectableRequest.emit
node_modules/follow-redirects/index.js:38:24 in eventHandlers.<computed>
node:events:527:28 in ClientRequest.emit
node:_http_client:478:9 in TLSSocket.socketOnEnd
node:events:539:35 in TLSSocket.emit
node:internal/streams/readable:1344:12 in endReadableNT
node:internal/process/task_queues:82:21 in process.processTicksAndRejections
node_modules/axios/dist/node/axios.cjs:3876:41 in Axios.request
node:internal/process/task_queues:95:5 in process.processTicksAndRejections
node_modules/deepl-node/dist/client.js:180:30 in async Function.sendAxiosRequest
node_modules/deepl-node/dist/client.js:143:28 in async HttpClient.sendRequestWithBackoff
node_modules/deepl-node/dist/index.js:363:41 in async Translator.translateText

To Reproduce
We haven't found a way to reproduce.

Expected behavior
Do not fail with "socket hang up", maybe another error more descriptive.

Additional info
The update of follow-redirects was because this security update:

Bump follow-redirects from 1.15.4 to 1.15.6 (#161) Bumps follow-redirects from 1.15.4 to 1.15.6. - Release notes - Commits

Uncaught TypeError: os.type is not a function

I become this error when i initialise the repository

Uncaught TypeError: os.type is not a function
at Translator.constructUserAgentString (deepl-node.js?v=e2e7fb1a:3446:33)
at new Translator (deepl-node.js?v=e2e7fb1a:3116:30)
at main.js:8:20
constructUserAgentString @ deepl-node.js?v=e2e7fb1a:3446
Translator @ deepl-node.js?v=e2e7fb1a:3116
(anonym) @ main.js:8

Bad request on unsupported formality

Currently, a request that specifies a formality setting not yet supported by DeepL returns an error without a translation.
DeepLError: Bad request, message: 'formality' is not supported for given 'target_lang'.

Maybe a more user friendly alternative would be to just ignore any unsupported options in the request, possibly attaching a warning message to the response informing the user of their mistake. This way, applications that call the DeepL api won't break when supplied an invalid configuration.

Issue with axios 1.2.0: "DeepLError: Error parsing response JSON: SyntaxError"

If axios v1.2.0 is used, the following error can occur when calling many library functions (e.g. getUsage()):
DeepLError: Error parsing response JSON: SyntaxError: Unexpected token in JSON at position 0

We have released v1.7.2 as a workaround: this updates the dependency requirement to disallow version axios v1.2.0, and are working on a fix.

Circular dependency index.js ➜ parsing.js ➜ index.js

Describe the bug

When building my Svelte app that uses deepl-node, I get a warning about circular dependencies:

Circular dependency: node_modules/.pnpm/[email protected]/node_modules/deepl-node/dist/index.js -> node_modules/.pnpm/[email protected]/node_modules/deepl-node/dist/parsing.js -> node_modules/.pnpm/[email protected]/node_modules/deepl-node/dist/index.js

To Reproduce
Steps to reproduce the behavior:

  1. Create a (Svelte) app
  2. Install, import (and use?) deepl-node in your code
  3. Build it

Expected behavior
The warning not to appear by refactoring your code

Desktop (please complete the following information):

  • OS: macOS
  • Browser: Arc
  • Version: 1.39.0

XML tags with attributes change the order of the translation when tagHandling is XML but are OK when tagHandling is off

Describe the bug
I am translating a text using Deepl API that contains XML tags and some of these tags include custom attributes; ex.

That’s the <fontcolor="#007af2">timer</fontcolor>! It measures the time you spend in a module OR the time you have left to complete a challenge!

However, the format of the XML tag is not conserved when the text is translated to Slovenian and Italian (I have not tested in other languages but could be the case for others as well). The result is like this:

Slovenian: To je časovnik <fontcolor="#007af2"></fontcolor> ! Meri čas, ki ga porabite v modulu, ALI čas, ki vam je ostal do konca izziva!

Italian: Questo è il timer <fontcolor="#007af2"></fontcolor> ! Misura il tempo trascorso in un modulo O il tempo rimasto per completare una sfida!

Meaning that instead of putting the word timer inside the tag, it gets out and leaves the tag empty. This happens when the tagHandling option is set to either XML or HTML, however if I set the tagHandling to off, the result is OK but other problems occur for my text because the tagHandling is set to off.

To Reproduce
Steps to reproduce the behavior:
Can be reproduced in the Deepl API Simulator: https://www.deepl.com/en/docs-api/simulator/

  1. Go to Deepl API Simulator
  2. Copy the text That’s the <fontcolor="#007af2">timer</fontcolor>! It measures the time you spend in a module OR the time you have left to complete a challenge! in the Text field.
  3. Set the target language to Slovenian or Italian
  4. Set tagHandling to XML
  5. Click on Send and compare the results with when the tagHandling is set to off

Expected behavior
The correct text should be:

Slovenian: To je <fontcolor="#007af2">časomer</fontcolor>! Meri čas, ki ga porabite v modulu, ALI čas, ki vam je ostal za dokončanje izziva!

Italian: È il <fontcolor="#007af2">timer</fontcolor>! Misura il tempo trascorso in un modulo O il tempo rimanente per completare una sfida!

Which is the case when the tagHandling is set to off but that should not be the case.

What has been tested

I tried combining different options together to see if I can make it work but none of them gave me the intended result. These are the parameters that I changed:

SentenceSplitting=on,off,noNewLines
preserveFormatting=on,off
nonSplittingTags=fontcolor,null

UPDATE 07/10/2023 11:47 AM
The problem seems to be the fact that the API takes into account the ="#007af2" part of the tag as the name of the tag and it doesn't see the closing tag for the same thing. So if we add a space: <fontcolor "=#007af2"> , it will work as expected. I don't know if a fix for that would be necessary but maybe a support for custom attributes like this would be nice.

Is it possible to get the alternatives of the phrase as well ?

When using the translator in the website we are able to get alternatives along with the translated phrase. For example I'm translating the word friend into Czech language and I'm getting the following result:

image

When using deepl-node API I'm only getting a single string in return which seems to be the original translation. Is it possible to get a translation response including these alternatives ? If not, why not ?

Thanks

Does this package work with webpack?

I'm trying to implement this package while using webpack, and each time there always seems to be a new problem. Is it just not possible to use deepl-node with webpack?

getting overcharged 9 times more

Describe the bug
A clear and concise description of what the bug is.

Since DeepL API does not understand text in multiple lines, I query just like below. encodeURIComponent() is a solution that I was actually suggested by DeepL support.

const inputText = encodeURIComponent(translateText);
const responseDeepL = await axios.post(
      deeplURL,
      `text=${inputText}&target_lang=${targetLang}`,
      {
        headers: {
          Authorization: `DeepL-Auth-Key ${DEEPL_KEY}`,
          "Content-Type": "application/x-www-form-urlencoded",
          "User-Agent": "axios 1.2.0-alpha.1",
        },
      }
    );

The problem is the volume of string becomes way larger than the original input.
For example,

const inputText = "こんにちは";
console.log( encodeURIComponent(inputText).length ) // this is 45 characters
console.log( inputText.length ) // this is 5 characters

I am currently receiving 9x overcharges on this issue.

[tests] Jest may incorrectly detect open handles when running the tests

Describe the bug
See fix in jest: jestjs/jest#13414
Unfortunately, this version of Jest (29.2+) requires Node 14.

To Reproduce
In the console, running tests may give a warning similar to the following

$ node_modules/.bin/jest --detectOpenHandles --no-cache tests/
 PASS  tests/general.test.ts
 PASS  tests/glossary.test.ts (24.288 s)
 PASS  tests/translateDocument.test.ts (31.975 s)
 PASS  tests/translateText.test.ts (6.858 s)

Test Suites: 4 passed, 4 total
Tests:       11 skipped, 50 passed, 61 total
Snapshots:   0 total
Time:        66.442 s
Ran all test suites matching /tests\//i.

Jest has detected the following 2 open handles potentially keeping Jest from exiting:

  ●  TLSWRAP

      220 |     ): Promise<{ statusCode: number; content: TContent }> {
      221 |         try {
    > 222 |             const response = await axios.request(axiosRequestConfig);
          |                                          ^
      223 |
      224 |             if (axiosRequestConfig.responseType === 'text') {
      225 |                 // Workaround for axios-bug: https://github.com/axios/axios/issues/907

      at node_modules/nock/lib/intercept.js:427:16
      at Object.module.request (node_modules/nock/lib/common.js:96:14)
      at RedirectableRequest.Object.<anonymous>.RedirectableRequest._performRequest (node_modules/follow-redirects/index.js:284:24)
      at new RedirectableRequest (node_modules/follow-redirects/index.js:66:8)
      at Object.request (node_modules/follow-redirects/index.js:523:14)
      at dispatchHttpRequest (node_modules/axios/lib/adapters/http.js:436:21)
      at node_modules/axios/lib/adapters/http.js:143:5
      at wrapAsync (node_modules/axios/lib/adapters/http.js:123:10)
      at http (node_modules/axios/lib/adapters/http.js:149:10)
      at Axios.dispatchRequest (node_modules/axios/lib/core/dispatchRequest.js:51:10)
      at Axios.request (node_modules/axios/lib/core/Axios.js:148:33)
      at Function.wrap [as request] (node_modules/axios/lib/helpers/bind.js:5:15)
      at Function.sendAxiosRequest (src/client.ts:222:42)
      at HttpClient.sendRequestWithBackoff (src/client.ts:176:45)
      at Translator.translateText (src/index.ts:571:63)
      at Object.<anonymous> (tests/translateText.test.ts:19:41)
      at TestScheduler.scheduleTests (node_modules/@jest/core/build/TestScheduler.js:333:13)
      at runJest (node_modules/@jest/core/build/runJest.js:404:19)
      at _run10000 (node_modules/@jest/core/build/cli/index.js:320:7)
      at runCLI (node_modules/@jest/core/build/cli/index.js:173:3)


  ●  TLSWRAP

      220 |     ): Promise<{ statusCode: number; content: TContent }> {
      221 |         try {
    > 222 |             const response = await axios.request(axiosRequestConfig);
          |                                          ^
      223 |
      224 |             if (axiosRequestConfig.responseType === 'text') {
      225 |                 // Workaround for axios-bug: https://github.com/axios/axios/issues/907

      at node_modules/nock/lib/intercept.js:427:16
      at Object.module.request (node_modules/nock/lib/common.js:96:14)
      at RedirectableRequest.Object.<anonymous>.RedirectableRequest._performRequest (node_modules/follow-redirects/index.js:284:24)
      at new RedirectableRequest (node_modules/follow-redirects/index.js:66:8)
      at Object.request (node_modules/follow-redirects/index.js:523:14)
      at dispatchHttpRequest (node_modules/axios/lib/adapters/http.js:436:21)
      at node_modules/axios/lib/adapters/http.js:143:5
      at wrapAsync (node_modules/axios/lib/adapters/http.js:123:10)
      at http (node_modules/axios/lib/adapters/http.js:149:10)
      at Axios.dispatchRequest (node_modules/axios/lib/core/dispatchRequest.js:51:10)
      at Axios.request (node_modules/axios/lib/core/Axios.js:148:33)
      at Function.wrap [as request] (node_modules/axios/lib/helpers/bind.js:5:15)
      at Function.sendAxiosRequest (src/client.ts:222:42)
      at HttpClient.sendRequestWithBackoff (src/client.ts:176:45)
      at Translator.translateText (src/index.ts:571:63)
      at Object.<anonymous> (tests/translateText.test.ts:221:41)
      at TestScheduler.scheduleTests (node_modules/@jest/core/build/TestScheduler.js:333:13)
      at runJest (node_modules/@jest/core/build/runJest.js:404:19)
      at _run10000 (node_modules/@jest/core/build/cli/index.js:320:7)
      at runCLI (node_modules/@jest/core/build/cli/index.js:173:3)

Expected behavior
Tests should run without throwing warnings.

Type 'string' is not assignable to type 'TargetLanguageCode'

Describe the bug
A clear and concise description of what the bug is.
[Type error]: I input the target language (string) but deepl.TargetLanguageCode does not allow it.

const defaultLang = "ja";
let typedTargetLang: deepl.TargetLanguageCode = defaultLang;

Type 'string' is not assignable to type 'TargetLanguageCode'.

To Reproduce
Steps to reproduce the behavior:

  1. Go to '...'
  2. Click on '....'
  3. Scroll down to '....'
  4. See error

Expected behavior
A clear and concise description of what you expected to happen.

Screenshots
If applicable, add screenshots to help explain your problem.

Desktop (please complete the following information):

  • OS: [e.g. iOS]
  • Browser [e.g. chrome, safari]
  • Version [e.g. 22]

Smartphone (please complete the following information):

  • Device: [e.g. iPhone6]
  • OS: [e.g. iOS8.1]
  • Browser [e.g. stock browser, safari]
  • Version [e.g. 22]

Additional context
Add any other context about the problem here.

Unable to resolve module fs | React native deepl-node integration

Hi, i am trying to integrate deepl-node with my react native app but i keep getting this error after following the installation steps
error message:
iOS Bundling failed 232ms
Unable to resolve module fs from C:\Users\oem\Desktop\Reway\Reway-App-Dev\node_modules\deepl-node\dist\index.js: fs could not be found within the project or in these directories:
node_modules
39 | const parsing_1 = require("./parsing");
40 | const utils_1 = require("./utils");

41 | const fs = __importStar(require("fs"));
| ^
42 | const http_1 = require("http");
43 | const path_1 = __importDefault(require("path"));
44 | const url_1 = require("url");

Translating HTML with English text to French adds HTML Tags and full sentence that is not in the input text

Describe the bug
When translating a English text with HTML elements to French, the response contains unexpected additional HTML Tags and often a full sentence that was not in the input.

To Reproduce
Minimal JS Script to reproduce the Error (last tested on March 9th 2024 6PM CET)

const deepl = require('deepl-node')
const authKey = "<authkey>"
const translator = new deepl.Translator(authKey)

async function translate(targetLang) {
	const result = await translator.translateText('<p><strong>Testing the system</strong></p>', 'en', targetLang, tag_handling = 'html')
	console.log(result)
}

translate('de')
translate('fr')

This results in the following responses:

{
  text: '<p><strong>Test des Systems</strong></p>',
  detectedSourceLang: 'en'
}
{
  text: "</p><strong>Tester le système</strong></p><strong></p><strong>La mise en place d'un système de gestion de l'information est une priorité.",
  detectedSourceLang: 'en'
}

The German translation is correct but the French translation has <strong></p><strong>La mise en place d'un système de gestion de l'information est une priorité. appended to a seemingly correct result.

I've noticed that without the <strong> Tag it does not happen but I have not tested that exhaustively.

Thank you very much.

[QUESTION] Temporary glosseries

This is not really an issue, but rather a question, and possibly feature request.
Would it be possible to have some kind of temporary glossaries, that you could pass as an argument in a translate request, without having to create a glossary?

To give a more precise example, here is my use case:

I am building a translation tool that would allow automatically translating strings from one language to a bunch of other languages.
Those strings may contain parameters (something like The count is [count].).
Sometimes, the translation result will rightly place the parameter like a word in a sentence, keeping its original form.
Sometimes it will also translate the parameter's name.
I would like to keep the original parameter name, without creating a glossary that would hold values on your side, when I only need them once.

This is admittedly much more complex than just a stipped-down glossary feature, but that would already be a start.

I hope you were able to understand my thoughts and hope this is somewhat usable feedback, but I am completly aware of its complexity and would not be surprised if it never finds its way onto future updates.

Also I apologize for my english if you didn't understand everything, I'm not a native speaker and I try not to use Deepl but to talk by myself as much as I can (ironically haha).

Deepl Limitations - Timeout Errors during concurrent calls

Hello,

I am utilizing the PRO Deepl API and have encountered some challenges related to concurrent requests while using the Deepl-Node client.

Here's the scenario: I have a service hosted on Azure, leveraging Azure Functions. Within this setup, there are 15 concurrent functions that attempt to translate a total of 72 KiB of text. The translateText<string[]> function takes an array of strings as input. The interesting aspect is that when these 15 functions are triggered, I encounter 'timeout' errors for all the requests. It's important to note that all these functions run on the same Virtual Machine, which implies that a single Deepl Client is employed to handle these 15 concurrent requests.

My questions are as follows:

  • Are there any limitations on the number of concurrent calls per Deepl Client or per API Key?
  • Would it be advisable to reduce the number of concurrent calls? If so, what would be an appropriate threshold in your opinion?
  • The current timeout configuration is set to 30000ms.

Your insights and guidance on optimizing these concurrent translation calls would be greatly appreciated. The service aim to translate ~1 000 000 000 characters.

Please be aware that the translation process functions correctly when a single request is made. This singular request encompasses the following elements:

An array input containing 600 texts (It is noteworthy to mention that the documentation indicates a limit of 50 texts per request.)
A maximum of 72 KiB of text, equating to a request payload of approximately 76 KiB (It is important to acknowledge that the documentation specifies a payload size allowance of up to 128 KiB. However, I have observed that if the payload size exceeds 85 KiB, it results in a '413 - Payload Too Large' error).

Could you provide more information regarding the limits documented?

SSL error using node 17+

Describe the bug
All requests result in the following error:

C:\Projects\ext\translate-doc\node_modules\deepl-node\dist\client.js:163
            const error = new errors_1.ConnectionError(`Connection failure: ${message}`);
                          ^

ConnectionError: Connection failure: write EPROTO 98720000:error:0A000152:SSL routines:final_renegotiate:unsafe legacy renegotiation disabled:c:\ws\de
ps\openssl\openssl\ssl\statem\extensions.c:922:

    at HttpClient.sendAxiosRequest (C:\Projects\ext\translate-doc\node_modules\deepl-node\dist\client.js:163:27)
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async HttpClient.sendRequestWithBackoff (C:\Projects\ext\translate-doc\node_modules\deepl-node\dist\client.js:114:28)
    at async Translator.translateText (C:\Projects\ext\translate-doc\node_modules\deepl-node\dist\index.js:355:41)
    at async file:///C:/Projects/ext/translate-doc/index.js:7:20 {
  error: AxiosError: write EPROTO 98720000:error:0A000152:SSL routines:final_renegotiate:unsafe legacy renegotiation disabled:c:\ws\deps\openssl\opens
sl\ssl\statem\extensions.c:922:

      at AxiosError.from (C:\Projects\ext\translate-doc\node_modules\axios\dist\node\axios.cjs:836:14)
      at RedirectableRequest.handleRequestError (C:\Projects\ext\translate-doc\node_modules\axios\dist\node\axios.cjs:3010:25)
      at RedirectableRequest.emit (node:events:525:35)
      at eventHandlers.<computed> (C:\Projects\ext\translate-doc\node_modules\follow-redirects\index.js:14:24)
      at ClientRequest.emit (node:events:513:28)
      at TLSSocket.socketErrorListener (node:_http_client:502:9)
      at TLSSocket.emit (node:events:513:28)
      at emitErrorNT (node:internal/streams/destroy:151:8)
      at emitErrorCloseNT (node:internal/streams/destroy:116:3)
      at process.processTicksAndRejections (node:internal/process/task_queues:82:21)

The underlying issue is probably the following: https://stackoverflow.com/questions/74324019/allow-legacy-renegotiation-for-nodejs

This only occurs on Node 17+.

To Reproduce

  1. Install node 18 (possibly using nvm)
  2. Create a new basic npm project npm init with index.js
  3. npm install deepl-node
  4. Copy/paste the contents of the 'hello world' example
  5. Enter authKey
  6. node index.js
  7. Generates the above error.

Expected behavior
The translation is logged to the console

Desktop

  • OS: Windows
  • Node 18.16.1

Axios proxy as URL

The options parameter of the Translator constructor only takes one type of proxy as ProxyConfig (looks same as AxiosProxyConfig).
It would be useful to be able to use a proxy URL string as proxy parameter. An axios instance creation in the client should look like this:

import { HttpProxyAgent, HttpProxyAgent } from 'hpagent';
axios.create({
   proxy: true,
   httpsAgent: new HttpsProxyAgent({ proxy: 'http://user:[email protected]:4567' })
   httpAgent: new HttpProxyAgent({ proxy: 'http://user:[email protected]:4567' })
})

Would it be an improvement in flexibility?
I always use one secret for the whole proxy URL, so it would help a lot.

The most flexible approach would be to have an axiosInstanace parameter for the Translator constructor, but this would cause a lot of code rewrites :(

Spaces before XML tags are randomly removed in the translation and quotes around the tags might end up within the tag

Describe the bug
When using the latest version 1.13.0 of the Deepl NodeJS lib I notice an issue with XML tags.
When using source text Please start your '<x id=p1>Basic</x>' plan by clicking the button '<x id=p2>Accept</x>'., the translation gets different syntax around the <x></x> tags.

To Reproduce
Steps to reproduce the behavior:

  1. API integrated correctly in NodeJS project
  2. Call:
    const result = await translator.translateText("Please start your '<x id=p1>Basic</x>' plan by clicking the button '<x id=p2>Accept</x>'.", "en", "de", { tagHandling: 'xml' });
  3. The console output with the German translation:
    Bitte starten Sie Ihren<x id=p1>'Basic</x>'-Plan, indem Sie auf die Schaltfläche<x id=p2>'Akzeptieren</x>' klicken.
    
  4. Analysis of translation syntax:
  • The original English tags are surrounded by single quotes: '<x id=p1>Basic</x>', while in the German output the opening quote is moved within the tags: <x id=p1>'Basic</x>'
  • The original English opening tags have a space in front of them: your '<x id=p1>Basic</x>', while in the German output the opening tag is directly concatenated to the previous word: Ihren<x id=p1>'Basic</x>'
    The expected output should be:
    Bitte starten Sie Ihren '<x id=p1>Basic</x>'-Plan, indem Sie auf die Schaltfläche '<x id=p2>Akzeptieren</x>' klicken.
    
  1. Added parameters preserveFormatting: true, outlineDetection: true and nonSplittingTags: ['x'], but each individual or all possible combinations provide the same German output string.

Expected behavior
It's expected that formatting characters (like spaces) and other non-translatable characters (like quotes) around tags are maintained, especially when option preserveFormatting is set to true.

Update
After creating this post I did some more testing. It appears that the (single) quotes might be the issue. When using double quotes, the same issue occurs.
However, when removing the quotes around the XML tags:

const result = await translator.translateText("Please start your <x id=p1>Basic</x> plan by clicking the button <x id=p2>Accept</x>.", "en", "de", { tagHandling: 'xml' });

The output maintains the spaces around the tags ✅:

Bitte starten Sie Ihren <x id=p1>Basic-Plan</x>, indem Sie auf die Schaltfläche <x id=p2>Akzeptieren</x> klicken.

Update 2
After creating this post I noticed that I didn't use quotes for the value of attribute id (see table "With Attributes" at https://developers.deepl.com/docs/xml-and-html-handling/xml). So basically my input string was malformed XML.

However, when applying quotes around p1 and p2, the API still returns the same erroneous output:

const result = await translator.translateText("Please start your '<x id="p1">Basic</x>' plan by clicking the button '<x id="p2">Accept</x>'.", "en", "de", { tagHandling: 'xml' });

Question
Why doesn't the API handle quotes around XML tags properly?

Screenshots
N/A

Desktop (please complete the following information):

  • OS: macOS 14.5

Additional context

  • npm deepl-node 1.13.0
  • NodeJS 16.6.0

cause: Error: socket hang up when try to send many requests

I need to translate a lot of data, when i try to do translate in loop i got this error. How i can prevent this?

ConnectionError: Connection failure: socket hang up
at Function.sendAxiosRequest (/Users/matthew/IdeaProjects/backend/node_modules/deepl-node/dist/client.js:163:27)
at runMicrotasks ()
at processTicksAndRejections (node:internal/process/task_queues:96:5)
at async HttpClient.sendRequestWithBackoff (/Users/matthew/IdeaProjects/backend/node_modules/deepl-node/dist/client.js:114:28)
at async Translator.translateText (/Users/matthew/IdeaProjects/backend/node_modules/deepl-node/dist/index.js:354:41)
at async /Users/matthew/IdeaProjects/backend/lib/utils/formatDocsJSON.js:156:17
at async Promise.all (index 45)
at async /Users/matthew/IdeaProjects/backend/lib/utils/formatDocsJSON.js:140:16
at async Promise.all (index 3)
at async formatJsonFile (/Users/matthew/IdeaProjects/backend/lib/utils/formatDocsJSON.js:139:18)
at async main (/Users/matthew/IdeaProjects/backend/lib/utils/formatDocsJSON.js:34:5) {
error: AxiosError: socket hang up
at Function.AxiosError.from (/Users/matthew/IdeaProjects/backend/node_modules/axios/dist/node/axios.cjs:789:14)
at RedirectableRequest.handleRequestError (/Users/matthew/IdeaProjects/backend/node_modules/axios/dist/node/axios.cjs:2744:25)
at RedirectableRequest.emit (node:events:525:35)
at ClientRequest.eventHandlers. (/Users/matthew/IdeaProjects/backend/node_modules/follow-redirects/index.js:14:24)
at ClientRequest.emit (node:events:513:28)
at TLSSocket.socketOnEnd (node:_http_client:518:9)
at TLSSocket.emit (node:events:525:35)
at endReadableNT (node:internal/streams/readable:1358:12)
at processTicksAndRejections (node:internal/process/task_queues:83:21) {
code: 'ECONNRESET',
config: {
transitional: [Object],
adapter: [Array],
transformRequest: [Array],
transformResponse: [Array],
timeout: 20000,
xsrfCookieName: 'XSRF-TOKEN',
xsrfHeaderName: 'X-XSRF-TOKEN',
maxContentLength: -1,
maxBodyLength: -1,
env: [Object],
validateStatus: null,
headers: [AxiosHeaders],
url: '/v2/translate',
method: 'post',
baseURL: 'https://api.deepl.com',
responseType: 'text',
data: 'target_lang=en-US&source_lang=de&text=Apikoaortales%2C+klappentragendes+Konduit'
},
request: Writable {
_writableState: [WritableState],
_events: [Object: null prototype],
_eventsCount: 3,
_maxListeners: undefined,
_options: [Object],
_ended: true,
_ending: true,
_redirectCount: 0,
_redirects: [],
_requestBodyLength: 79,
_requestBodyBuffers: [Array],
_onNativeResponse: [Function (anonymous)],
_currentRequest: [ClientRequest],
_currentUrl: 'https://api.deepl.com/v2/translate',
_timeout: null,
[Symbol(kCapture)]: false
},
cause: Error: socket hang up
at connResetException (node:internal/errors:705:14)
at TLSSocket.socketOnEnd (node:_http_client:518:23)
at TLSSocket.emit (node:events:525:35)
at endReadableNT (node:internal/streams/readable:1358:12)
at processTicksAndRejections (node:internal/process/task_queues:83:21) {
code: 'ECONNRESET'
}
},
shouldRetry: false
}

This is my configutration deepl.Translator(config.deeplApiKey, { maxRetries: 50, minTimeout: 20000 });

`.translateText` function overload is not exhaustively typed

Summary

Your definition of .translateText runs into this canonically known typescript issue. It expects the language compiler to exhaustively perform a combinatorically expensive type casting which is not supported.

Code

type TranslationText = string | string[];
const firstTextToTranslate: TranslationText = 'hello world';
const secondTextToTranslate: TranslationText = ['hello world'];

deepl.translateText(firstTextToTranslate, ...);
/* yields compiler error:
No overload matches this call.
  Overload 1 of 2, '(texts: string, sourceLang: SourceLanguageCode | null, targetLang: TargetLanguageCode, options?: TranslateTextOptions | undefined): Promise<...>', gave the following error.
    Argument of type 'string | string[]' is not assignable to parameter of type 'string'.
      Type 'string[]' is not assignable to type 'string'.
  Overload 2 of 2, '(texts: string[], sourceLang: SourceLanguageCode | null, targetLang: TargetLanguageCode, options?: TranslateTextOptions | undefined): Promise<...>', gave the following error.
    Argument of type 'string | string[]' is not assignable to parameter of type 'string[]'.
      Type 'string' is not assignable to type 'string[]'.ts(2769)
*/

// on the other hand...
deepl.translateText(secondTextToTranslate, ...);
/* yields the same compiler error: */

Expected Behaviour

Typescript/your type definitions should be able to deduce that your function supports both types of inputs

Solution Proposition

As the Typescript team already made very clear that they are not planning to implement a combinatorically expensive feature, we have to work around this.

The typescript docs on conditional types state that overloading is unnecessary and your function definition could be done in a single, stable go with some generics and conditional types.

  async translateText<T extends string | string[]>(
      texts: T,
      sourceLang: SourceLanguageCode | null,
      targetLang: TargetLanguageCode,
      options?: TranslateTextOptions,
  ): Promise<T extends string ? TextResult : TextResult[]>

Translator Option 'serverUrl' is misleading

Describe the bug

According to RFC1738 a HTTP URL takes the form of http://<host>:<port>/<path>?<searchpart>.

When setting the serverUrl in the TranslatorOptions, it only replaces the host:port part.

To Reproduce

Construct a new Translator:

const translator = new deepl.Translator(
      process.env.DEEPL_API_KEY,
      {
          serverUrl: 'http://some-other-host.com/resource',
        },
    );

Translate something through this translator and the server at http://some-other-host.com will receive POST /resource/v2/translate HTTP/1.1.

Expected behavior

The option should replace the whole URL and not add its own path to the request.
Alternatively, it should be renamed to use the proper terminology, e.g. replaceHostAndPort.

oe.URLSearchParams is not a constructor Error

I have tried to use this library but when I run my code I get the following error in the browser console:

index.3240d547.js:10 Uncaught (in promise) TypeError: oe.URLSearchParams is not a constructor
    at je (index.3240d547.js:10:69597)
    at a.Translator.translateText (index.3240d547.js:10:73014)
    at Le (index.3240d547.js:10:71558)

Desktop (please complete the following information):

  • OS: Windows 10
  • Browser Electron/19.1.8
  • Version [e.g. 22]
  • Node 16.15.0

Additional context
I'm using typescript and have no errors when I build my app - only when I run it. However, I'm not a professional programmer so it's possible I've installed the wrong version of something. My tsconfig.json file is below:

{
  "compilerOptions": {
    "lib": [
      "es2021",
      "dom"
    ],
    "module": "commonjs",
    "target": "es2021",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true,
    "moduleResolution": "node"
  }
}

and my package.json

{
  "name": "logseq-deepl-integration",
  "version": "0.0.1",
  "description": "Translate selected blocks via deepl",
  "main": "dist/index.html",
  "targets": {
    "main": false
  },
  "scripts": {
    "build": "parcel build --no-source-maps index.html --public-url ./",
    "dev": "parcel build --no-optimize index.html --public-url ./"
  },
  "author": "dcoales",
  "license": "MIT",
  "dependencies": {
    "@logseq/libs": "^0.0.10",
    "deepl-node": "^1.7.3"
  },
  "logseq": {
    "id": "logseq-deepl",
    "title": "Logseq Deepl Integration",
    "author": "dcoales",
    "description": "Translate selected blocks via deepl"
  },
  "devDependencies": {
    "@types/jest": "^29.0.3",
    "@types/node": "^18.11.9",
    "buffer": "^5.5.0",
    "events": "^3.3.0",
    "parcel": "^2.8.0",
    "path-browserify": "^1.0.1",
    "punycode": "^1.4.1",
    "querystring-es3": "^0.2.1",
    "stream-http": "^3.2.0",
    "ts-node": "^10.9.1",
    "typescript": "^4.8.3",
    "url": "^0.11.0",
    "util": "^0.12.5"
  }
}

I'm running this as a plugin to a tool called LogSeq. The plugin code is below. Any help would be much appreciated. Thanks.

import '@logseq/libs';
import {BlockEntity} from "@logseq/libs/dist/LSPlugin";
import { SettingSchemaDesc } from '@logseq/libs/dist/LSPlugin.user';
import * as deepl from 'deepl-node';
import {TextResult} from "deepl-node";

/**
 * entry
 */

function main() {

    logseq.useSettingsSchema(settings);

    logseq.Editor.registerSlashCommand('Get Jira Details for Selection', (_) => {
        return translate();
    })

    logseq.App.registerCommand('deeplTranslate', {
        key: 'deeplTranslate',
        label: 'Translate the selected lines',
        desc: 'Get translations for each of the currently selected lines',
        keybinding: {binding: 'mod+alt+t'}
    }, (e) => {
        return translate();
    })
}

async function translate() {
    let selection: BlockEntity[] | null = await logseq.Editor.getSelectedBlocks();
   //console.log(selection);
    if (!selection || selection.length === 0) {
        const block: BlockEntity | null = await logseq.Editor.getCurrentBlock();
        if (block){
            selection = [block];
        }
    }
    const lines:string[] = [];
    if (selection){
        for (let b of selection){
            lines.push(b.content);
        }
    }

    const authKey = logseq.settings?.APIToken;
    const translator = new deepl.Translator(authKey);
    const results:TextResult[] = await translator.translateText(lines,null,logseq.settings?.language);
    results.map((result: deepl.TextResult) => {
        console.log(result.text);
    });
}

const settings: SettingSchemaDesc[] = [
    {
        key: "language",
        description: "The language for the translated text",
        type: "string",
        default: "pl",
        title: "Translated text language",
    },
    {
        key: "APIToken",
        description: "Deepl API token",
        type: "string",
        default: "",
        title: "Deepl API token",
    }
];

logseq.ready(main).catch(console.error);

url_1.URLSearchParams is not a constructor

Hi,

I'm trying to build a node app with vite using : npm create vite@latest

when using your code example after installing npm install deepl-node:

import './style.css'
import * as deepl from 'deepl-node';

const authKey = "...-...-...-...-...:fx"; // Replace with your key
const translator = new deepl.Translator(authKey);

(async () => {
    const result = await translator.translateText('Hello, world!', null, 'fr');
    console.log(result.text); // Bonjour, le monde !
})();

I get the following error:

Uncaught (in promise) TypeError: url_1.URLSearchParams is not a constructor
    at buildURLSearchParams (index.js:123:26)
    at Translator.translateText (index.js:354:22)
    at main.js?t=1656189862004:12:37
    at main.js?t=1656189862004:14:3

I have a free account with DeepL

Thanks! (I'm pretty new to this ;-)

translation using arrays does not work

Good day, i am trying to translate a big array with deepl. Somehow when i put even a small array in the translateText function i am getting an error:

DeepLError: texts parameter must not be a non-empty string or array of non-empty strings at appendTextsAndReturnIsSingular projectpath/node_modules/deepl-node/dist/index.js:166:23

It seems that arrays are not supported

translator.translateText(
['hallo', 'test'],
req.body.sourceLanguageCode, //this is nl
req.body.targetLanguageCode, // this is en-GB
)

Ionic & Angular ReferenceError when initializing deepl.Translator

Describe the bug
ReferenceError when initializing deepl.Translator

To Reproduce
Steps to reproduce the behavior:

  1. Running a project with Ionic 6 and Angular 15 (typescript)
  2. Adding the starter code from the README

Expected behavior
Expected no issues and a console log that it was successful

Screenshots
image
image

Desktop (please complete the following information):

  • OS: Windows
  • Browser Chrome
  • Version 111.0.5563.66

Additional context
I am not sure what is going on. At first I thought it was a circular import issue but I have made sure I am not calling this anywhere else. I have deleted and generated a new page and I still get these issues at all times. I really need some help in understanding the approach I am doing wrong here. I appreciate all your help and please let me know if there is anything else I would need to provide.

If I remove the line const translator = new deepl.Translator(authkey);, everything runs fine.

downloadDocument() response is empty for PDFs

Describe the bug
When downloading PDFs via translator.downloadDocument(), the resulting file is always empty and the file size is always 2KB. It seems that only the file's metadata is downloaded (see below), but the content itself is wiped out.

This is running inside a Lambda on AWS.

Note: .txt files work as expected.

To Reproduce
Steps to reproduce the behavior:

Upload code

const myBuffer = fs.readFileSync(files["deepl-file-to-upload"].path);
console.log(`my buffer length: ${myBuffer.length}`); // <-- Buffer length is 143KB 
translator.uploadDocument(
        myBuffer,
        `EN`,
        `DE`,
        { filename: `${files["deepl-file-to-upload"].name}` }
      ).then((uploadResult) => {
        console.log(uploadResult); // Returns documentId + documentKey as expected
      }).catch((err) => {
        console.log(err);
        reject(err);
});

Download code

let builtDocumentHandle = {
          'documentId': documentId,
          'documentKey': documentKey
};

let myFileName = `translate-result-${builtDocumentHandle.documentId}.${fileType}`; // Define file name
let attachmentPath = `/tmp/${myFileName}`; // Build path where we will temporarily store file after it's been downloaded
let myWS = fs.createWriteStream(`/tmp/${myFileName}`); // Create write stream to hold the downloaded file
            
// Download newly translated document from DeepL
translator.downloadDocument(
    builtDocumentHandle,
    myWS
).then(() => {

   // Check download file size for debug purposes
    try {
        let myFileSize = getFilesizeInBytes(attachmentPath);
        console.log(`deepl file size after download: ${myFileSize} bytes`); // <-- Always returns around 2KB for PDFs
    } catch (error) {
        console.log('filesize error');
        console.log(error);
    }

}).catch((err) => {
    console.log(err);
});

function getFilesizeInBytes(filename) {
  var stats = fs.statSync(filename);
  var fileSizeInBytes = stats.size;
  return fileSizeInBytes;
}

Expected behavior
The downloaded PDF document should include all translated content.

Screenshots
If applicable, add screenshots to help explain your problem.

Desktop (please complete the following information):
Chrome Version 113.0.5672.126

Additional context

Example PDF content that I'm getting back from the DeepL API

%PDF-1.7
5 0 obj
<</Type /Page/Parent 3 0 R/Contents 6 0 R/MediaBox [0 0 612 792]/Resources<<>>/Group <</Type/Group/S/Transparency/CS/DeviceRGB>>>>
endobj
6 0 obj
<</Length 7 0 R>>stream
1 0 0 -1 0 792 cm q 1 0 0 1 86 91 cm q 1 0 0 1 3.852 0 cm Q Q 1 0 0 -1 -0 792 cm 
endstream
endobj
7 0 obj
81 
endobj
8 0 obj
<</Type /Page/Parent 3 0 R/Contents 9 0 R/MediaBox [0 0 612 792]/Resources<<>>/Group <</Type/Group/S/Transparency/CS/DeviceRGB>>>>
endobj
9 0 obj
<</Length 10 0 R>>stream
1 0 0 -1 0 792 cm q 1 0 0 1 86 91 cm Q 1 0 0 -1 -0 792 cm 
endstream
endobj
10 0 obj
58 
endobj
1 0 obj
<</Keywords(���,� �d�o�c�I�d�:�C�E�C�6�4�8�3�6�7�9�5�B�F�E�C�8�B�1�2�9�E�0�E�F�2�0�8�A�C�7�E�E)/Creator(���M�i�c�r�o�s�o�f�t� �O�f�f�i�c�e� �W�o�r�d)/Producer(���A�s�p�o�s�e�.�W�o�r�d�s� �f�o�r� �.�N�E�T� �2�3�.�1�.�0)/CreationDate(D:20230608155704Z)/ModDate(D:20230608155704Z)>>
endobj
2 0 obj
<</Type /Catalog/Pages 3 0 R/Lang(en-US)/Metadata 4 0 R>>
endobj
3 0 obj
<</Type /Pages/Count 2/Kids[5 0 R 8 0 R ]>>
endobj
4 0 obj
<</Type /Metadata/Subtype /XML/Length 11 0 R>>stream
<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?>
<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="PDFNet">
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
<rdf:Description rdf:about="" xmlns:xmp="http://ns.adobe.com/xap/1.0/">
<xmp:CreateDate>2023-06-08T15:57:04Z</xmp:CreateDate>
<xmp:ModifyDate>2023-06-08T15:57:04Z</xmp:ModifyDate>
<xmp:CreatorTool>Microsoft Office Word</xmp:CreatorTool>
</rdf:Description>
<rdf:Description rdf:about="" xmlns:dc="http://purl.org/dc/elements/1.1/">
<dc:format>application/pdf</dc:format>
</rdf:Description>
<rdf:Description rdf:about="" xmlns:pdf="http://ns.adobe.com/pdf/1.3/">
<pdf:Keywords>, docId:CEC64836795BFEC8B129E0EF208AC7EE</pdf:Keywords>
<pdf:Producer>Aspose.Words for .NET 23.1.0</pdf:Producer>
</rdf:Description>
</rdf:RDF>
</x:xmpmeta>
<?xpacket end="w"?>

endstream
endobj
11 0 obj
826 
endobj
12 0 obj
<</Type /XRef/W [1 4 2]/Size 13/Info 1 0 R/Root 2 0 R/ID [<395C0EA322A4574B9446E6B21AB973A7><395C0EA322A4574B9446E6B21AB973A7>]/Length 91>>stream
�����������[���������������������������
�������������'������=�������������D����������������
endstream
endobj
startxref
1973
%%EOF

The API doesn't translate English to Spanish when there's a small typo; it just returns the English text. However, it works for English to French.

Describe the bug
I try to translate Hello darkness my old friend Ive come to talk with you again to Spanish gives Hello darkness my old friend Ive come to talk with you again.
However with French and Italian it works correctly

To Reproduce
Steps to reproduce the behavior:
Use the API To Translate English to Spanish
Hello darkness my old friend Ive come to talk with you again to Spanish gives Hello darkness my old friend Ive come to talk with you again.

Expected behavior
It should translate to Spanish

Timestamp: 2024-06-25 22:15:42

Error Spanish
image

Correct Spanish No Typo
image

Working French
image

tag handling

I'm using deepl-node with node v16.14.0

I am having issue in very specific translations from fr to en-gb when there is only one sentence, markup and ponctuations

🔴<p>C'est bien d'avoir fait ça !</p>-> <It's good that you did that!
<p>C'est bien d'avoir fait ça !</p><p>Non ?</p><p>Si bien sûr</p> -> <p>It's good that you did that!</p><p>Didn't you?</p><p>Yes of course</p>
<p>C'est bien d'avoir fait ça</p> -> <p>It's good to have done this</p>

I have tried these options without success tag_handling: 'xml' tag_handling: 'html' splitSentences : 'off' preserveFormatting: true

Thanks for your help

Translation w/ glossary entries are only partially translated and include sourceLang string

Describe the bug
After creating a glossary and running a test translation, the glossary entry provided was partially translated and the source entry is sometimes included in the translation.

To Reproduce
Steps to reproduce the behavior:

  1. I have created a glossary from EN to DE
  2. I have added some entries to test the functionality
  3. Results as seen in the screenshot below are not sticking to the terms set in the glossary.

image

This is the code I'm calling the translations with:

  const testTranslation3 = await translator.translateText('test1', 'en', 'de', {
    glossary: glossaryId,
  })

Expected behavior
I'm uncertain if I misunderstood how glossaries work, but I thought they would always take precedence over default translations. Also, the source language string should never show up in the translation.

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.