2021-01-12 11:20:54 -07:00
|
|
|
const authHeader = require('./auth-header');
|
|
|
|
const makeRequest = require('./make-request');
|
|
|
|
|
2021-02-02 20:50:04 -07:00
|
|
|
const isReservedHeading = (context, str) => {
|
|
|
|
const reservedHeadings = [
|
|
|
|
'after-user-code',
|
|
|
|
'answers',
|
|
|
|
'before-user-code',
|
|
|
|
'description',
|
|
|
|
'fcc-editable-region',
|
|
|
|
'hints',
|
|
|
|
'instructions',
|
|
|
|
'question',
|
|
|
|
'seed',
|
|
|
|
'seed-contents',
|
|
|
|
'solutions',
|
|
|
|
'text',
|
|
|
|
'video-solution'
|
|
|
|
];
|
|
|
|
const captureGroupStr = `(${reservedHeadings.join('|')})`;
|
|
|
|
const regex = new RegExp(`--${captureGroupStr}--`);
|
|
|
|
return !!(context.match(/^Headline/) && str.match(regex));
|
|
|
|
};
|
|
|
|
|
2021-01-12 11:20:54 -07:00
|
|
|
const isCode = str => /^\/pre\/code|\/code$/.test(str);
|
|
|
|
|
2021-02-03 01:00:56 -07:00
|
|
|
const isTitle = str => str.endsWith('title');
|
2021-02-02 20:50:04 -07:00
|
|
|
|
|
|
|
const shouldHide = (text, context, challengeTitle, crowdinFilePath) => {
|
|
|
|
if (crowdinFilePath.endsWith('.yml')) {
|
|
|
|
return !isTitle(context);
|
|
|
|
}
|
|
|
|
if (isReservedHeading(context, text) || isCode(context)) {
|
2021-01-12 11:20:54 -07:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return text !== challengeTitle && context.includes('id=front-matter');
|
|
|
|
};
|
|
|
|
|
|
|
|
const getStrings = async ({ projectId, fileId }) => {
|
|
|
|
let headers = { ...authHeader };
|
2021-02-02 20:50:04 -07:00
|
|
|
let done = false;
|
|
|
|
let offset = 0;
|
|
|
|
let strings = [];
|
|
|
|
while (!done) {
|
|
|
|
let endPoint = `projects/${projectId}/strings?limit=500&offset=${offset}`;
|
|
|
|
if (fileId) {
|
|
|
|
endPoint += `&fileId=${fileId}`;
|
|
|
|
}
|
|
|
|
const response = await makeRequest({ method: 'get', endPoint, headers });
|
|
|
|
if (response.data) {
|
|
|
|
if (response.data.length) {
|
|
|
|
strings = [...strings, ...response.data];
|
|
|
|
offset += 500;
|
|
|
|
} else {
|
|
|
|
done = true;
|
|
|
|
return strings;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
const { error, errors } = response;
|
|
|
|
console.error(error ? error : errors);
|
|
|
|
}
|
2021-01-12 11:20:54 -07:00
|
|
|
}
|
2021-02-02 20:50:04 -07:00
|
|
|
return null;
|
2021-01-12 11:20:54 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
const updateString = async ({ projectId, stringId, propsToUpdate }) => {
|
|
|
|
let headers = { ...authHeader };
|
|
|
|
const endPoint = `projects/${projectId}/strings/${stringId}`;
|
|
|
|
const body = propsToUpdate.map(({ path, value }) => ({
|
|
|
|
op: 'replace',
|
|
|
|
path,
|
|
|
|
value
|
|
|
|
}));
|
|
|
|
await makeRequest({
|
|
|
|
method: 'patch',
|
|
|
|
endPoint,
|
|
|
|
headers,
|
|
|
|
body
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
const changeHiddenStatus = async (projectId, stringId, newStatus) => {
|
|
|
|
await updateString({
|
|
|
|
projectId,
|
|
|
|
stringId,
|
|
|
|
propsToUpdate: [{ path: '/isHidden', value: newStatus }]
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
const updateFileStrings = async ({ projectId, fileId, challengeTitle }) => {
|
|
|
|
const fileStrings = await getStrings({
|
|
|
|
projectId,
|
|
|
|
fileId
|
|
|
|
});
|
|
|
|
|
|
|
|
for (let {
|
|
|
|
data: { id: stringId, text, isHidden, context }
|
|
|
|
} of fileStrings) {
|
|
|
|
const hideString = shouldHide(text, context, challengeTitle);
|
|
|
|
if (!isHidden && hideString) {
|
|
|
|
changeHiddenStatus(projectId, stringId, true);
|
|
|
|
} else if (isHidden && !hideString) {
|
|
|
|
changeHiddenStatus(projectId, stringId, false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2021-02-02 20:50:04 -07:00
|
|
|
const updateFileString = async ({
|
|
|
|
projectId,
|
|
|
|
string,
|
|
|
|
challengeTitle,
|
|
|
|
crowdinFilePath
|
|
|
|
}) => {
|
2021-01-18 11:20:29 -07:00
|
|
|
const {
|
|
|
|
data: { id: stringId, text, isHidden, context }
|
|
|
|
} = string;
|
2021-02-02 20:50:04 -07:00
|
|
|
const hideString = shouldHide(text, context, challengeTitle, crowdinFilePath);
|
2021-01-18 11:20:29 -07:00
|
|
|
if (!isHidden && hideString) {
|
|
|
|
await changeHiddenStatus(projectId, stringId, true);
|
|
|
|
console.log(
|
|
|
|
`${challengeTitle} - stringId: ${stringId} - changed isHidden to true`
|
|
|
|
);
|
|
|
|
} else if (isHidden && !hideString) {
|
|
|
|
await changeHiddenStatus(projectId, stringId, false);
|
|
|
|
console.log(
|
|
|
|
`${challengeTitle} - stringId: ${stringId} - changed isHidden to false`
|
|
|
|
);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2021-02-23 23:45:02 -07:00
|
|
|
const getStringTranslations = async ({ projectId, stringId, languageId }) => {
|
|
|
|
let headers = { ...authHeader };
|
|
|
|
let done = false;
|
|
|
|
let offset = 0;
|
|
|
|
let translations = [];
|
|
|
|
while (!done) {
|
|
|
|
let endPoint = `projects/${projectId}/translations?stringId=${stringId}&languageId=${languageId}&limit=500&offset=${offset}`;
|
|
|
|
const response = await makeRequest({ method: 'get', endPoint, headers });
|
|
|
|
if (response.data) {
|
|
|
|
if (response.data.length) {
|
|
|
|
translations = [...translations, ...response.data];
|
|
|
|
offset += 500;
|
|
|
|
} else {
|
|
|
|
done = true;
|
|
|
|
return translations;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
const { error, errors } = response;
|
|
|
|
console.error(
|
|
|
|
error ? JSON.stringify(error, null, 2) : JSON.stringify(errors, null, 2)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
};
|
|
|
|
|
|
|
|
const deleteTranslation = async (projectId, translationId) => {
|
|
|
|
let headers = { ...authHeader };
|
|
|
|
const endPoint = `projects/${projectId}/translations/${translationId}`;
|
|
|
|
await makeRequest({
|
|
|
|
method: 'delete',
|
|
|
|
endPoint,
|
|
|
|
headers
|
|
|
|
});
|
|
|
|
console.log(`Deleted translationId ${translationId} from Crowdin project`);
|
|
|
|
return null;
|
|
|
|
};
|
|
|
|
|
|
|
|
const addTranslation = async (projectId, stringId, languageId, text) => {
|
|
|
|
let headers = { ...authHeader };
|
|
|
|
const endPoint = `projects/${projectId}/translations`;
|
|
|
|
const body = {
|
|
|
|
stringId,
|
|
|
|
languageId,
|
|
|
|
text
|
|
|
|
};
|
|
|
|
const response = await makeRequest({
|
|
|
|
method: 'post',
|
|
|
|
endPoint,
|
|
|
|
headers,
|
|
|
|
body
|
|
|
|
});
|
|
|
|
if (response.data) {
|
|
|
|
return response.data;
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
};
|
|
|
|
|
|
|
|
const getLanguageTranslations = async ({ projectId, languageId }) => {
|
|
|
|
let headers = { ...authHeader };
|
|
|
|
let done = false;
|
|
|
|
let offset = 0;
|
|
|
|
let translations = [];
|
|
|
|
while (!done) {
|
|
|
|
let endPoint = `projects/${projectId}/languages/${languageId}/translations?limit=500&offset=${offset}`;
|
|
|
|
const response = await makeRequest({ method: 'get', endPoint, headers });
|
|
|
|
if (response.data) {
|
|
|
|
if (response.data.length) {
|
|
|
|
translations = [...translations, ...response.data];
|
|
|
|
offset += 500;
|
|
|
|
} else {
|
|
|
|
done = true;
|
|
|
|
return translations;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
const { error, errors } = response;
|
|
|
|
console.error(
|
|
|
|
error ? JSON.stringify(error, null, 2) : JSON.stringify(errors, null, 2)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
};
|
|
|
|
|
2021-03-06 21:45:51 -07:00
|
|
|
const deleteLanguageTranslations = async (projectId, languageId, stringId) => {
|
|
|
|
let headers = { ...authHeader };
|
|
|
|
const endPoint = `projects/${projectId}/translations?languageId=${languageId}&stringId=${stringId}`;
|
|
|
|
console.log(`deleting ${stringId}...`);
|
|
|
|
await makeRequest({
|
|
|
|
method: 'delete',
|
|
|
|
endPoint,
|
|
|
|
headers
|
|
|
|
});
|
|
|
|
return null;
|
|
|
|
};
|
|
|
|
|
2021-01-12 11:20:54 -07:00
|
|
|
module.exports = {
|
|
|
|
getStrings,
|
|
|
|
updateString,
|
2021-01-18 11:20:29 -07:00
|
|
|
updateFileStrings,
|
2021-02-23 23:45:02 -07:00
|
|
|
updateFileString,
|
|
|
|
getStringTranslations,
|
|
|
|
addTranslation,
|
|
|
|
deleteTranslation,
|
2021-03-06 21:45:51 -07:00
|
|
|
getLanguageTranslations,
|
2021-06-17 11:24:56 -07:00
|
|
|
deleteLanguageTranslations,
|
|
|
|
changeHiddenStatus
|
2021-01-12 11:20:54 -07:00
|
|
|
};
|