medusa-plugin-tolgee
Version:
Medusa V2 Plugin to easily add translations to your models with Tolgee
160 lines • 15.6 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const utils_1 = require("@medusajs/utils");
const common_1 = require("../../common");
const axios_1 = __importDefault(require("axios"));
class TolgeeModuleService {
constructor({ tolgeeClient, logger }, options) {
this.client_ = tolgeeClient;
this.logger = logger;
this.options_ = {
...options,
keys: {
...common_1.defaultSupportedProperties,
...options.keys,
},
};
}
async getOptions() {
try {
// TODO: axios-cache-interceptor type mismatch
const { data: languages } = await this.client_.get(`/languages`, {
params: { size: 9999 },
// use transformResponse to also cache computation.
// concat to the existing transforms gives JSON deserial. automatically
transformResponse: axios_1.default.defaults.transformResponse.concat((data) => {
const languages = data?._embedded?.languages;
if (!languages || languages.length < 1)
return {
defaultLanguage: "en",
availableLanguages: []
};
const defaultLanguage = languages.find((lang) => lang.base)?.tag ?? languages[0].tag;
const availableLanguages = languages.map((lang) => ({
label: lang.name,
tag: lang.tag,
}));
return { defaultLanguage, availableLanguages };
})
});
return {
...languages,
apiKey: this.options_.apiKey,
apiUrl: this.options_.baseURL
};
}
catch (error) {
throw new utils_1.MedusaError(utils_1.MedusaError.Types.UNEXPECTED_STATE, `Failed to fetch languages for project: ${error.message}`);
}
}
async getModelKeyNames(id) {
try {
const response = await this.client_.get(`/keys/search?search=ns=${id}&size=9999`, { cache: false });
return response.data?._embedded?.keys?.map(k => k.name) ?? [];
}
catch (error) {
throw new utils_1.MedusaError(utils_1.MedusaError.Types.UNEXPECTED_STATE, `Failed to fetch key names for model ${id}: ${error.message}`);
}
}
async list(filter) {
try {
const country_code = filter.context?.country_code?.toLowerCase();
const ids = Array.isArray(filter.id) ? filter.id : [filter.id];
const langs = (await this.getOptions()).availableLanguages.map((lang) => lang.tag).join(",");
// We use separate queries to simplify caching, they get batched anyway
const data = await Promise.all(ids.map(id => this.client_.get(`/translations`, { params: { languages: `${langs}`, filterNamespace: `${id}`, size: 9999 }, id: `get-translation-${id}` })));
const keys = data.flatMap(d => d.data._embedded.keys);
// TODO: proper typing of Tolgee response and normalized result
const results = [];
for (const id of ids) {
const normalizedData = this.getNormalizedData(id, keys);
// If the locale is passed via context, directly return the keys for that locale. Simplifies user-side fetching
results.push({ id, ...(country_code ? normalizedData[country_code] : normalizedData) });
}
return results;
}
catch (error) {
throw new utils_1.MedusaError(utils_1.MedusaError.Types.UNEXPECTED_STATE, `Failed to fetch translations for key ID ${filter.id}: ${error.message}`);
}
}
getNormalizedData(id, keys) {
const data = {};
for (const key of keys) {
if (key.keyName.startsWith(id)) {
for (const language in key.translations) {
if (!data[language])
data[language] = {};
data[language][key.keyName.split(".")[1]] = key.translations[language].text;
}
}
}
return data;
}
async createNewKeyWithTranslation(keys) {
try {
const tolgeeOptions = await this.getOptions();
await this.client_.post(`/keys/import`, {
keys: keys.map(({ id, tags, keyName, translation }) => ({
name: `${id}.${keyName}`,
tags,
namespace: id,
translations: { [tolgeeOptions.defaultLanguage]: translation },
}))
}, {
cache: {
update: Object.fromEntries(keys.map(({ id }) => [`get-translation-${id}`, "delete"]))
}
});
return;
}
catch (error) {
this.logger.error(error);
throw new utils_1.MedusaError(utils_1.MedusaError.Types.UNEXPECTED_STATE, `Failed to import keys ${error}`);
}
}
async createModelTranslations(models, type) {
const keys = models.flatMap((model) => this.options_.keys?.[type]?.map((key) => ({
id: model.id,
tags: this.options_.tags?.[type] ?? [type],
keyName: key,
translation: model?.[key] ?? ""
})) ?? []);
try {
await this.createNewKeyWithTranslation(keys);
return models.map((model) => model.id);
}
catch (error) {
this.logger.error(`Entities of type ${type} already translated or error creating translations: ${models.map((model) => model.id)}`, error);
return [];
}
}
async getNamespaceKeys(id) {
const ids = Array.isArray(id) ? id : [id];
try {
const response = await this.client_.get(`/keys/select?filterNamespace=${ids.join(",")}`, { cache: false });
return response.data.ids;
}
catch (error) {
throw new utils_1.MedusaError(utils_1.MedusaError.Types.UNEXPECTED_STATE, `Failed to fetch namespace keys for ${id}: ${error.message}`);
}
}
async deleteTranslation(id) {
const keys = await this.getNamespaceKeys(id);
try {
const response = await this.client_.delete(`/keys/${keys}`, {
cache: {
update: { [`get-translation-${id}`]: "delete" }
}
});
return response.data;
}
catch (error) {
throw new utils_1.MedusaError(utils_1.MedusaError.Types.UNEXPECTED_STATE, `Failed to delete translations for namespace ${id}: ${error.message}`);
}
}
}
exports.default = TolgeeModuleService;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3NyYy9tb2R1bGVzL3RvbGdlZS9zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEsMkNBQTZDO0FBQzdDLHlDQUF3RztBQUV4RyxrREFBdUQ7QUFvQ3ZELE1BQU0sbUJBQW1CO0lBS3JCLFlBQVksRUFBRSxZQUFZLEVBQUUsTUFBTSxFQUF3RCxFQUFFLE9BQTJCO1FBQ25ILElBQUksQ0FBQyxPQUFPLEdBQUcsWUFBWSxDQUFBO1FBQzNCLElBQUksQ0FBQyxNQUFNLEdBQUcsTUFBTSxDQUFBO1FBRXBCLElBQUksQ0FBQyxRQUFRLEdBQUc7WUFDWixHQUFHLE9BQU87WUFDVixJQUFJLEVBQUU7Z0JBQ0YsR0FBRyxtQ0FBMEI7Z0JBQzdCLEdBQUcsT0FBTyxDQUFDLElBQUk7YUFDbEI7U0FDSixDQUFBO0lBQ0wsQ0FBQztJQUVELEtBQUssQ0FBQyxVQUFVO1FBQ1osSUFBSSxDQUFDO1lBQ0QsOENBQThDO1lBQzlDLE1BQU0sRUFBRSxJQUFJLEVBQUUsU0FBUyxFQUFFLEdBQUcsTUFBTyxJQUFJLENBQUMsT0FBeUIsQ0FBQyxHQUFHLENBQXFFLFlBQVksRUFBRTtnQkFDcEosTUFBTSxFQUFFLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRTtnQkFDdEIsbURBQW1EO2dCQUNuRCx1RUFBdUU7Z0JBQ3ZFLGlCQUFpQixFQUFHLGVBQUssQ0FBQyxRQUFRLENBQUMsaUJBQWdELENBQUMsTUFBTSxDQUFDLENBQUMsSUFBNkIsRUFBRSxFQUFFO29CQUN6SCxNQUFNLFNBQVMsR0FBRyxJQUFJLEVBQUUsU0FBUyxFQUFFLFNBQVMsQ0FBQTtvQkFDNUMsSUFBSSxDQUFDLFNBQVMsSUFBSSxTQUFTLENBQUMsTUFBTSxHQUFHLENBQUM7d0JBQ2xDLE9BQU87NEJBQ0gsZUFBZSxFQUFFLElBQUk7NEJBQ3JCLGtCQUFrQixFQUFFLEVBQUU7eUJBQ3pCLENBQUE7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