import Joi from 'joi' import { BaseJsonService, InvalidResponse, queryParam, pathParam, } from '../index.js' import { coveragePercentage } from '../color-formatters.js' const description = ` Localizely is a management system for translation, localization, and internationalization of your projects. The read-only API token from the Localizely account is required to fetch necessary data. Note: Do not use the default API token as it grants full read-write permissions to your projects. You will expose your project and allow malicious users to modify the translations at will. Instead, create a new one with only read permission. You can find more details regarding API tokens under My profile page. ` const schema = Joi.object({ strings: Joi.number().required(), reviewedProgress: Joi.number().required(), languages: Joi.array() .items( Joi.object({ langCode: Joi.string().required(), langName: Joi.string().required(), strings: Joi.number().required(), reviewed: Joi.number().required(), reviewedProgress: Joi.number().required(), }), ) .required(), }).required() const queryParamSchema = Joi.object({ token: Joi.string().required(), languageCode: Joi.string().regex(/^[a-z]{2}(-[A-Z][a-z]{3})?(-[A-Z]{2})?$/), }).required() export default class Localizely extends BaseJsonService { static category = 'other' static route = { base: 'localizely/progress', pattern: ':projectId/:branch*', queryParamSchema, } static openApi = { '/localizely/progress/{projectId}': { get: { summary: 'Localizely progress', description, parameters: [ pathParam({ name: 'projectId', example: '5cc34208-0418-40b1-8353-acc70c95f802', }), queryParam({ name: 'token', example: '0f4d5e31a44f48dcbab966c52cfb0a67c5f1982186c14b85ab389a031dbc225a', required: true, }), queryParam({ name: 'languageCode', example: 'en-US', required: false, }), ], }, }, '/localizely/progress/{projectId}/{branch}': { get: { summary: 'Localizely progress (branch)', description, parameters: [ pathParam({ name: 'projectId', example: '5cc34208-0418-40b1-8353-acc70c95f802', }), pathParam({ name: 'branch', example: 'main', }), queryParam({ name: 'token', example: '0f4d5e31a44f48dcbab966c52cfb0a67c5f1982186c14b85ab389a031dbc225a', required: true, }), queryParam({ name: 'languageCode', example: 'en-US', required: false, }), ], }, }, } static defaultBadgeData = { label: 'localized' } static render({ langName, reviewedProgress }) { return { label: langName || 'localized', message: `${reviewedProgress}%`, color: coveragePercentage(reviewedProgress), } } async fetch({ projectId, branch, apiToken }) { return this._requestJson({ schema, url: `https://api.localizely.com/v1/projects/${projectId}/status`, options: { searchParams: { branch }, headers: { 'X-Api-Token': apiToken }, }, httpErrors: { 403: 'not authorized for project', }, }) } static transform(json, languageCode) { if (!languageCode) { return { reviewedProgress: json.reviewedProgress } } const language = json.languages.find(lang => lang.langCode === languageCode) if (!language) { throw new InvalidResponse({ prettyMessage: 'Unsupported language' }) } const { langName, reviewedProgress } = language return { langName, reviewedProgress } } async handle({ projectId, branch }, { token: apiToken, languageCode }) { const json = await this.fetch({ projectId, branch, apiToken }) const { langName, reviewedProgress } = this.constructor.transform( json, languageCode, ) return this.constructor.render({ langName, reviewedProgress }) } }