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 })
}
}