Add translation for product names (#74)
This commit is contained in:
@@ -185,6 +185,11 @@ Resources:
|
|||||||
Action:
|
Action:
|
||||||
- s3:*
|
- s3:*
|
||||||
Resource: !Sub arn:aws:s3:::${UploadBucket}
|
Resource: !Sub arn:aws:s3:::${UploadBucket}
|
||||||
|
- Effect: Allow
|
||||||
|
Action:
|
||||||
|
- 'comprehend:DetectDominantLanguage'
|
||||||
|
- 'translate:TranslateText'
|
||||||
|
Resource: '*'
|
||||||
|
|
||||||
# A role for the containers
|
# A role for the containers
|
||||||
TaskRole:
|
TaskRole:
|
||||||
|
|||||||
@@ -25,7 +25,6 @@ export async function sendMessage(
|
|||||||
body: string,
|
body: string,
|
||||||
queueUrl: string,
|
queueUrl: string,
|
||||||
): Promise<SendMessageCommandOutput | undefined> {
|
): Promise<SendMessageCommandOutput | undefined> {
|
||||||
console.log('Senfing', body);
|
|
||||||
const client = new SQSClient({ region: 'eu-west-1' });
|
const client = new SQSClient({ region: 'eu-west-1' });
|
||||||
|
|
||||||
const params: SendMessageCommandInput = {
|
const params: SendMessageCommandInput = {
|
||||||
|
|||||||
@@ -28,12 +28,15 @@ import {
|
|||||||
} from './utils';
|
} from './utils';
|
||||||
import { UserInputError } from 'apollo-server';
|
import { UserInputError } from 'apollo-server';
|
||||||
import { sendPathChangedCmd } from '../bernard/client';
|
import { sendPathChangedCmd } from '../bernard/client';
|
||||||
|
import { TextsAPI } from './texts-api';
|
||||||
|
|
||||||
const MINUTE = 60;
|
const MINUTE = 60;
|
||||||
|
|
||||||
export class ProductAPI extends BaseSQLDataSource {
|
export class ProductAPI extends BaseSQLDataSource {
|
||||||
constructor(config) {
|
textsApi: TextsAPI;
|
||||||
|
constructor(config, textsApi) {
|
||||||
super(config);
|
super(config);
|
||||||
|
this.textsApi = textsApi;
|
||||||
}
|
}
|
||||||
|
|
||||||
// async getMaterial(printId: number): Promise<any> {
|
// async getMaterial(printId: number): Promise<any> {
|
||||||
@@ -384,6 +387,14 @@ export class ProductAPI extends BaseSQLDataSource {
|
|||||||
sendPathChangedCmd(oldProd.path, uniquePath);
|
sendPathChangedCmd(oldProd.path, uniquePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (oldProd.fields.name !== info.name) {
|
||||||
|
await this.textsApi.translateProductName(
|
||||||
|
info.name,
|
||||||
|
oldProd.path,
|
||||||
|
uniquePath,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
const promises = [];
|
const promises = [];
|
||||||
promises.push(
|
promises.push(
|
||||||
this.knex
|
this.knex
|
||||||
|
|||||||
@@ -0,0 +1,106 @@
|
|||||||
|
import { SQLDataSource } from 'datasource-sql';
|
||||||
|
import { TranslateInput, translateText } from '../aws/translate';
|
||||||
|
import { Locale } from '../types/market-locale-types';
|
||||||
|
import { MarketLocaleAPI } from './market-locale-api';
|
||||||
|
|
||||||
|
const MINUTE = 60;
|
||||||
|
|
||||||
|
// TODO: perhaps rename to MarketLocale API and add market_locales and locales here.
|
||||||
|
export class TextsAPI extends SQLDataSource {
|
||||||
|
marketLocaleApi: MarketLocaleAPI;
|
||||||
|
|
||||||
|
constructor(config, marketLocaleApi: MarketLocaleAPI) {
|
||||||
|
super(config);
|
||||||
|
this.marketLocaleApi = marketLocaleApi;
|
||||||
|
}
|
||||||
|
|
||||||
|
async translateProductName(name: string, oldPath, newPath): Promise<void> {
|
||||||
|
// Check if we have an entry already
|
||||||
|
const textKey = await this.upsertTextId(newPath, oldPath);
|
||||||
|
|
||||||
|
const locales = await this.marketLocaleApi.getLocales();
|
||||||
|
for (let i = 0; i < locales.length; i++) {
|
||||||
|
let langCode = this.getLanguageCode(locales[i]);
|
||||||
|
// If we have a fallback locale we skip translating
|
||||||
|
if (locales[i].fallbackId) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const input: TranslateInput = {
|
||||||
|
text: name,
|
||||||
|
targetLanguageCode: langCode,
|
||||||
|
};
|
||||||
|
const translated = await translateText(input);
|
||||||
|
|
||||||
|
await this.upsertTextDataEntry(textKey.textid, translated, locales[i].id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Upsert translated entry to the i18n-texts_data table
|
||||||
|
* @param text The translated text to insert
|
||||||
|
* @param localeId The id of the locale
|
||||||
|
*/
|
||||||
|
private async upsertTextDataEntry(
|
||||||
|
textId: number,
|
||||||
|
text: string,
|
||||||
|
localeId: number,
|
||||||
|
) {
|
||||||
|
// Check if we have an entry already
|
||||||
|
const textDataEntry = await this.knex
|
||||||
|
.select('*')
|
||||||
|
.from('i18n-texts_data')
|
||||||
|
.where({ textid: textId, locale_id: localeId })
|
||||||
|
.first();
|
||||||
|
|
||||||
|
if (textDataEntry) {
|
||||||
|
// Update existing entry
|
||||||
|
await this.knex('i18n-texts_data')
|
||||||
|
.where({ textid: textId, locale_id: localeId })
|
||||||
|
.update({ text: text });
|
||||||
|
} else {
|
||||||
|
//Insert new entry
|
||||||
|
await this.knex('i18n-texts_data').insert({
|
||||||
|
text: text,
|
||||||
|
textid: textId,
|
||||||
|
locale_id: localeId,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private getLanguageCode(locale: Locale) {
|
||||||
|
let langCode = locale.value.substr(0, 2);
|
||||||
|
return langCode == 'nn' ? 'no' : langCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Upsert translated entry to the i18n-texts table
|
||||||
|
* @param newKey the new name of the text key
|
||||||
|
* @param localeId the old name of the text key
|
||||||
|
*/
|
||||||
|
private async upsertTextId(newKey: string, oldKey: string) {
|
||||||
|
let textEntry = await this.knex
|
||||||
|
.select('*')
|
||||||
|
.from('i18n-texts')
|
||||||
|
.where({ name: oldKey })
|
||||||
|
.first();
|
||||||
|
|
||||||
|
let textId = textEntry?.textid;
|
||||||
|
// No entry, create one
|
||||||
|
if (!textId) {
|
||||||
|
const res = await this.knex('i18n-texts')
|
||||||
|
.insert({ name: newKey, category: 'productTitles' })
|
||||||
|
.returning('*');
|
||||||
|
|
||||||
|
textEntry = res[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update table if different
|
||||||
|
if (oldKey !== newKey) {
|
||||||
|
await this.knex
|
||||||
|
.table('i18n-texts')
|
||||||
|
.update({ name: newKey })
|
||||||
|
.where({ name: oldKey });
|
||||||
|
}
|
||||||
|
return textEntry;
|
||||||
|
}
|
||||||
|
}
|
||||||
+4
-2
@@ -18,6 +18,7 @@ import { InteriorAPI } from './datasources/interior-api';
|
|||||||
import { ClaimVerifyResult, verifyToken } from './cognito/cognito-client';
|
import { ClaimVerifyResult, verifyToken } from './cognito/cognito-client';
|
||||||
import { readFileSync } from 'fs';
|
import { readFileSync } from 'fs';
|
||||||
import { InteriorsLambdaAPI } from './datasources/interiors-lambda-api';
|
import { InteriorsLambdaAPI } from './datasources/interiors-lambda-api';
|
||||||
|
import { TextsAPI } from './datasources/texts-api';
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const typeDefs = readFileSync(
|
const typeDefs = readFileSync(
|
||||||
path.join(__dirname, './schema.graphql'),
|
path.join(__dirname, './schema.graphql'),
|
||||||
@@ -27,15 +28,16 @@ const typeDefs = readFileSync(
|
|||||||
const knexConfig = knexStringcase(dbConfig);
|
const knexConfig = knexStringcase(dbConfig);
|
||||||
|
|
||||||
// set up any dataSources our resolvers need
|
// set up any dataSources our resolvers need
|
||||||
|
const marketLocaleApi = new MarketLocaleAPI(knexConfig);
|
||||||
|
const textsApi = new TextsAPI(knexConfig, marketLocaleApi);
|
||||||
const categoryApi = new CategoryAPI(knexConfig);
|
const categoryApi = new CategoryAPI(knexConfig);
|
||||||
const designerApi = new DesignerAPI(knexConfig);
|
const designerApi = new DesignerAPI(knexConfig);
|
||||||
const imageServerApi = new ImageServerApi();
|
const imageServerApi = new ImageServerApi();
|
||||||
const interiorsLambdaApi = new InteriorsLambdaAPI();
|
const interiorsLambdaApi = new InteriorsLambdaAPI();
|
||||||
const interiorApi = new InteriorAPI(knexConfig, imageServerApi);
|
const interiorApi = new InteriorAPI(knexConfig, imageServerApi);
|
||||||
const keywordApi = new KeywordAPI(knexConfig);
|
const keywordApi = new KeywordAPI(knexConfig);
|
||||||
const marketLocaleApi = new MarketLocaleAPI(knexConfig);
|
|
||||||
const orderApi = new OrderAPI(knexConfig);
|
const orderApi = new OrderAPI(knexConfig);
|
||||||
const productApi = new ProductAPI(knexConfig);
|
const productApi = new ProductAPI(knexConfig, textsApi);
|
||||||
|
|
||||||
const dataSources = () => ({
|
const dataSources = () => ({
|
||||||
categoryApi,
|
categoryApi,
|
||||||
|
|||||||
Reference in New Issue
Block a user