fkirc / attranslate

A command line tool for translating JSON, YAML, CSV, ARB, XML (via a CLI)
https://www.npmjs.com/package/attranslate
Other
335 stars 27 forks source link

Azure Info #200

Closed MuchoDart closed 2 years ago

MuchoDart commented 2 years ago

Great project!

I'm trying to configure attranslate to work with the Azure translator. Unfortunately, I'm not getting very far and I can't find any documentation that explains how to configure it.

Any pointers / documentation would be appreciated.

Thanks!

fkirc commented 2 years ago

Azure should work with the following two options:

--service One of "manual", "sync-without-translate", "google-translate", "azure" --serviceConfig supply configuration for a translation service (either a path to a key-file or an API-key)

So you could pass —service=azure —serviceConfig=yourApiKey Please let me know if this works.

MuchoDart commented 2 years ago

Thanks for your prompt response.

I got a little further. Below is the command I'm using, and the response I get.

$ attranslate --srcFile=./lib/l10n/intl_messages.arb --srcLng=en --srcFormat=arb --targetFormat=arb --service=azure --serviceConfig="Ocp-Apim-Subscription-Key:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" --cacheDir=flutter --targetFile=./lib/l10n/intl_es.arb --targetLng=es

Invoke 'azure' from 'en' to 'es' with 3 inputs...
An error occurred:
Azure Translation failed: {"error":{"code":401000,"message":"The request is not authorized because credentials are missing or invalid."}}
Error: Azure Translation failed: {"error":{"code":401000,"message":"The request is not authorized because credentials are missing or invalid."}}
    at AzureTranslator.translateBatch (/opt/emsdk/node/14.15.5_64bit/lib/node_modules/attranslate/dist/services/azure-translator.js:26:19)
    at processTicksAndRejections (internal/process/task_queues.js:93:5)
    at async Promise.all (index 0)
    at async AzureTranslator.translateStrings (/opt/emsdk/node/14.15.5_64bit/lib/node_modules/attranslate/dist/services/azure-translator.js:40:25)
    at async runTranslationService (/opt/emsdk/node/14.15.5_64bit/lib/node_modules/attranslate/dist/core/invoke-translation-service.js:62:24)
    at async invokeTranslationService (/opt/emsdk/node/14.15.5_64bit/lib/node_modules/attranslate/dist/core/invoke-translation-service.js:29:28)
    at async translateCore (/opt/emsdk/node/14.15.5_64bit/lib/node_modules/attranslate/dist/core/translate-core.js:106:29)
    at async translateCli (/opt/emsdk/node/14.15.5_64bit/lib/node_modules/attranslate/dist/core/translate-cli.js:84:20)

The value passed to --serviceConfig is correct; it works using the curl command:

$ curl -X POST "https://api.cognitive.microsofttranslator.com/translate?api-version=3.0&to=es" -H "Ocp-Apim-Subscription-Key:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" -H "Content-Type: application/json" -d "[{'Text':'Hello, what is your name?'}]"

[{"detectedLanguage":{"language":"en","score":1.0},"translations":[{"text":"Hola, ¿cómo te llamas?","to":"es"}]}]

In this curl example, the Azure API is using the header to authenticate with the key. Does attranslate use the header in a similar fashion?

fkirc commented 2 years ago

Here is the relevant code: https://github.com/fkirc/attranslate/blob/master/src/services/azure-translator.ts

attranslate passes the following headers to Azure: headers: { "Ocp-Apim-Subscription-Key": apiKey, "Content-Type": "application/json; charset=UTF-8", },

So it seems to me that you need the following change: Instead of --serviceConfig="Ocp-Apim-Subscription-Key:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", I would try to pass --serviceConfig="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

MuchoDart commented 2 years ago

That was actually my initial attempt, but it gives me this error.

$ attranslate --srcFile=./lib/l10n/intl_messages.arb --srcLng=en --srcFormat=arb --targetFormat=arb --service=azure --serviceConfig="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" --cacheDir=flutter --targetFile=./lib/l10n/intl_es.arb --targetLng=es

Invoke 'azure' from 'en' to 'es' with 3 inputs...
An error occurred:
Cannot read property 'text' of undefined
TypeError: Cannot read property 'text' of undefined
    at /opt/emsdk/node/14.15.5_64bit/lib/node_modules/attranslate/dist/services/azure-translator.js:31:45
    at Array.map (<anonymous>)
    at AzureTranslator.translateBatch (/opt/emsdk/node/14.15.5_64bit/lib/node_modules/attranslate/dist/services/azure-translator.js:29:21)
    at processTicksAndRejections (internal/process/task_queues.js:93:5)
    at async Promise.all (index 0)
    at async AzureTranslator.translateStrings (/opt/emsdk/node/14.15.5_64bit/lib/node_modules/attranslate/dist/services/azure-translator.js:40:25)
    at async runTranslationService (/opt/emsdk/node/14.15.5_64bit/lib/node_modules/attranslate/dist/core/invoke-translation-service.js:62:24)
    at async invokeTranslationService (/opt/emsdk/node/14.15.5_64bit/lib/node_modules/attranslate/dist/core/invoke-translation-service.js:29:28)
    at async translateCore (/opt/emsdk/node/14.15.5_64bit/lib/node_modules/attranslate/dist/core/translate-core.js:106:29)
    at async translateCli (/opt/emsdk/node/14.15.5_64bit/lib/node_modules/attranslate/dist/core/translate-cli.js:84:20)
fkirc commented 2 years ago

I think your initial attempt was correct, so the error is probably an incompatibility between client-code and API-response. To fix this error, would you be willing to provide me an Azure API-key for testing-purposes? Right now, the attranslate-project is lacking API-keys for properly testing Azure-functionality. Of course I will ensure that API-keys are never leaked to the public and only invoke a small number of test-translations.

MuchoDart commented 2 years ago

Great. Let me try a couple of things first. If I don't have any luck, I'll provide you with a key for troubleshooting.

Thanks!

MuchoDart commented 2 years ago

I did a little digging. It looks like the Azure call is working OK. The problem occurs in processing the response from the service. I couldn't follow the logic after that.

Let me know what's the best way to send you the key.

MuchoDart commented 2 years ago

A little more info. The payload form the Azure service looks like this.

data:  [
  { translations: [ { text: 'Apple', to: 'en' } ] },
  { translations: [ { text: 'Pear', to: 'en' } ] },
  { translations: [ { text: '{currentPage} of {numberOfPages}', to: 'en' } ] }
]

If I change line 54 in azure-translator.ts from:

translated: res.translations[i].text,

to

translated: res.translations[0].text,

everything works. I'm not sure why the code, as written doesn't work though.

fkirc commented 2 years ago

Okay so it looks like you already figured out a working fix that could be deployed with the next update? The best way to send me the API-key is via mail.

MuchoDart commented 2 years ago

From the Azure docs: https://docs.microsoft.com/en-us/azure/cognitive-services/translator/reference/v3-0-translate#response-body

If you won't be translating more than one language at a time, then it should be safe to use array index [0]. So, yes, this should be a simple fix to the problem.

API-key sent.

fkirc commented 2 years ago

Thank you for your detailed analysis and proposed bugfix, I agree with your conclusions. I received your API-key via mail and I will release an update of attranslate over the weekend.

MuchoDart commented 2 years ago

Fantastic! Thanks you for your attention to this matter.

fkirc commented 2 years ago

I published 1.6.2 to fix the bug. Please let me know if an issue still persists.

MuchoDart commented 2 years ago

All good. 1.6.2 works perfectly! Thanks!