I'm not sure if I worded the question right. Here is my problem. I am trying to translate my webpage dynamically using Cognitive Services Translator from Microsoft. I made a react hook with the translator. This works fine if I just need to translate one value in an object.
const useAzureTranslate = (data: any, lang: string, objKey: string) => {
const [translatedData, setTranslatedData] = useState<any | null>([]);
useEffect(() => {
Promise.all(data.map(function (obj: any) {
return axios({
baseURL: endpoint,
url: '/translate',
method: 'post',
headers: {
'Ocp-Apim-Subscription-Key': subscriptionKey,
'Ocp-Apim-Subscription-Region': location,
'Content-type': 'application/json',
'X-ClientTraceId': uuidv4().toString()
},
params: {
'api-version': '3.0',
'from': 'en',
'to': lang
},
data: [{ "text": obj[objKey] }],
responseType: 'json'
}).then(response => {
// console.log(response.data)
let translatedText = response.data[0].translations[0].text;
return { ...obj, [objKey]: translatedText };
}).catch((error) => {
console.log(error.response.data.error);
throw error;
});
})).then(newDataArray => {
// console.log(newDataArray);
setTranslatedData(newDataArray);
}).catch(err => {
console.log(err);
throw err;
});
console.log(translatedData);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [lang])
return { translatedData };
}
I want to be able to have an array of keys instead of having to translate just one key value. I am not sure how to go about this.
The "/translate"
API can take up to 100 terms to translate.
Request body
The body of the request is a JSON array. Each array element is a JSON object with a string property named Text, which represents the string to translate.
[ {"Text":"I would really like to drive your car around the block a few times."} ]
The following limitations apply:
- The array can have at most 100 elements.
- The entire text included in the request cannot exceed 10,000 characters including spaces.
If your code remains within these constraints then I suggest the following:
objKey
to be declared as an array of stringsobjKey
array to an array of objects with text
keyobj
objectExample:
const useAzureTranslate = (data: any, lang: string, objKey: string[]) => {
const [translatedData, setTranslatedData] = useState<any | null>([]);
useEffect(() => {
Promise.all(
data.map(function (obj: any) {
return axios({
baseURL: endpoint,
url: "/translate",
method: "post",
headers: {
"Ocp-Apim-Subscription-Key": subscriptionKey,
"Ocp-Apim-Subscription-Region": location,
"Content-type": "application/json",
"X-ClientTraceId": uuidv4().toString()
},
params: {
"api-version": "3.0",
from: "en",
to: lang
},
data: objKey.map((key) => ({ text: obj[key] })), // <-- array of "text" objects
responseType: "json"
})
.then((response) => {
// Reduce array of translations back into current `obj` copy
return response.data[0].translations.reduce(
(newObj, { text }, index) => ({
...newObj,
[objKey[index]]: text
}),
{ ...obj }
);
})
.catch((error) => {
console.log(error.response.data.error);
throw error;
});
})
)
.then((newDataArray) => {
setTranslatedData(newDataArray);
})
.catch((err) => {
console.log(err);
throw err;
});
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [lang]);
return { translatedData };
};
If your code is outside the constraints then you'll need to chunk up your data and/or key translation terms first, then make the requests as above.