UNPKG

@shawnvogt/strapi-plugin-google-translate

Version:

Strapi plugin for automated translation of content using Google Cloud Translation

185 lines (164 loc) 5.62 kB
const _ = require('lodash') const { stripIds } = require('./strip-ids') async function getRelevantLocalization(contentType, id, locale) { const { preserveUpstreamRelations } = strapi.config.get('plugin.gct') const relationContent = await strapi .service(contentType) .findOne(id, { populate: 'localizations' }) const localization = relationContent.localizations.filter( (l) => l.locale === locale )[0] if (!localization) { const body = await strapi .service(contentType) .findOne(id, { populate: '*' }) const ctx = { request: { body: { data: body, sourceLocale: body.locale, targetLocale: locale, contentTypeUid: contentType, inEditor: false, }, }, } const translatedData = await strapi .plugin('gct') .controller('gctController') .translate(ctx) const strippedData = await stripIds( translatedData, preserveUpstreamRelations ) await strapi.controller(contentType).createLocalization({ is: () => false, request: { body: { ...strippedData, locale: locale, }, }, params: { id: id, }, }) return getRelevantLocalization(contentType, id, locale) } return relationContent.localizations.filter((l) => l.locale === locale)[0] } /** * Translate relations by either copying, deleting or using the corresponding locale * @param {object} data The data to translate * @param {object} schema The schema of the content-type * @param {string} targetLocale The target locale (iso-format) * @returns The input data with relations either * - copied in the case they can be resued * - deleted if they cannot be reused * - translated if the relation target is localized and the related instance has the targetLocale created */ async function translateRelations(data, schema, targetLocale) { const { translateRelations: shouldTranslateRelations } = strapi.config.get('plugin.gct') const attributesSchema = _.get(schema, 'attributes', []) const resultData = _.cloneDeep(data) await Promise.all( Object.keys(attributesSchema).map(async (attr) => { if (attr === 'localizations') { return } const attributeData = _.get(data, attr, undefined) if (attributeData === null || attributeData === undefined) { return } const attributeSchema = attributesSchema[attr] if (attributeSchema.type === 'relation') { resultData[attr] = shouldTranslateRelations ? await translateRelation( attributeData, attributeSchema, targetLocale ) : undefined } else if (attributeSchema.type === 'component') { resultData[attr] = await translateComponent( attributeData, attributeSchema, targetLocale ) } else if (attributeSchema.type === 'dynamiczone') { resultData[attr] = await Promise.all( attributeData.map((object) => translateComponent(object, attributeSchema, targetLocale) ) ) } }) ) return resultData } async function translateComponent(data, componentReference, targetLocale) { const componentSchema = componentReference.type === 'dynamiczone' ? strapi.components[data.__component] : strapi.components[componentReference.component] if (componentReference.repeatable) { return await Promise.all( data.map((value) => translateRelations(value, componentSchema, targetLocale) ) ) } return await translateRelations(data, componentSchema, targetLocale) } async function translateRelation(attributeData, attributeSchema, targetLocale) { const relationSchema = strapi.contentTypes[attributeSchema.target] const relationIsLocalized = _.get( relationSchema, 'pluginOptions.i18n.localized', false ) const relationIsBothWays = _.has(attributeSchema, 'inversedBy', false) || _.has(attributeSchema, 'mappedBy', false) // If the relation is localized, the relevant localizations from the relation should be selected if (relationIsLocalized) { // for oneToMany and manyToMany relations there are multiple relations possible, so all of them need to be considered if ( ['oneToMany', 'manyToMany'].includes(attributeSchema.relation) && attributeData?.length > 0 ) { return _.compact( await Promise.all( attributeData.map(async (prevRelation) => getRelevantLocalization( attributeSchema.target, prevRelation.id, targetLocale ) ) ) ) } else if ( ['oneToOne', 'manyToOne'].includes(attributeSchema.relation) && attributeData ) { return getRelevantLocalization( attributeSchema.target, attributeData.id, targetLocale ) } } else if ( relationIsBothWays && ['oneToOne', 'oneToMany'].includes(attributeSchema.relation) ) { // In this case the relations in other locales or in the referenced relations would be deleted // so there is not really a different option than to not include these relations return attributeSchema.relation == 'oneToMany' ? [] : undefined } return attributeData } module.exports = { translateRelations, }