extract-translations.js 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. const path = require('path');
  2. const fs = require('fs-extra');
  3. const spawn = require('cross-spawn');
  4. const { exec } = require('child_process');
  5. const MESSAGES_DIR = path.join(__dirname, '../src/lib/static/i18n-messages');
  6. extractTranslations().then(
  7. () => {
  8. process.exit(0);
  9. },
  10. (error) => {
  11. console.log(error);
  12. process.exit(1);
  13. },
  14. );
  15. /**
  16. * Extracts translation tokens into the i18n-messages files found in the MESSAGES_DIR.
  17. */
  18. async function extractTranslations() {
  19. const locales = fs.readdirSync(MESSAGES_DIR).map((file) => path.basename(file).replace('.json', ''));
  20. const report = {
  21. generatedOn: new Date().toISOString(),
  22. lastCommit: await getLastGitCommitHash(),
  23. translationStatus: {},
  24. };
  25. for (const locale of locales) {
  26. const outputPath = path.join(
  27. path.relative(path.join(__dirname, '..'), MESSAGES_DIR),
  28. `${locale}.json`,
  29. );
  30. console.log(`Extracting translation tokens for "${outputPath}"`);
  31. try {
  32. await runExtraction(locale);
  33. const { tokenCount, translatedCount, percentage } = getStatsForLocale(locale);
  34. console.log(`${locale}: ${translatedCount} of ${tokenCount} tokens translated (${percentage}%)`);
  35. console.log('');
  36. report.translationStatus[locale] = { tokenCount, translatedCount, percentage };
  37. } catch (e) {
  38. console.log(e);
  39. }
  40. }
  41. const reportFile = path.join(__dirname, '../i18n-coverage.json');
  42. fs.writeFileSync(reportFile, JSON.stringify(report, null, 2), 'utf-8');
  43. console.log(`Report saved to "${reportFile}"`);
  44. }
  45. function runExtraction(locale) {
  46. const command = 'npm';
  47. const args = getNgxTranslateExtractCommand(locale);
  48. return new Promise((resolve, reject) => {
  49. try {
  50. const child = spawn(`yarnpkg`, args, { stdio: ['pipe', 'pipe', process.stderr] });
  51. child.on('close', (x) => {
  52. resolve();
  53. });
  54. child.on('error', (err) => {
  55. reject(err);
  56. });
  57. } catch (e) {
  58. reject(e);
  59. }
  60. });
  61. }
  62. function getStatsForLocale(locale) {
  63. const content = fs.readJsonSync(path.join(MESSAGES_DIR, `${locale}.json`), 'utf-8');
  64. let tokenCount = 0;
  65. let translatedCount = 0;
  66. for (const section of Object.keys(content)) {
  67. const sectionTranslations = Object.values(content[section]);
  68. tokenCount += sectionTranslations.length;
  69. translatedCount += sectionTranslations.filter((val) => val !== '').length;
  70. }
  71. const percentage = Math.round((translatedCount / tokenCount) * 100);
  72. return {
  73. tokenCount,
  74. translatedCount,
  75. percentage,
  76. };
  77. }
  78. function getNgxTranslateExtractCommand(locale) {
  79. return [
  80. `ngx-translate-extract`,
  81. '--input',
  82. './src',
  83. '--output',
  84. `./src/lib/static/i18n-messages/${locale}.json`,
  85. `--clean`,
  86. `--sort`,
  87. `--format`,
  88. `namespaced-json`,
  89. `--format-indentation`,
  90. `" "`,
  91. `-m`,
  92. `_`,
  93. ];
  94. }
  95. function getLastGitCommitHash() {
  96. return new Promise((resolve, reject) => {
  97. exec('git rev-parse HEAD', (err, result) => {
  98. if (err) {
  99. reject(err);
  100. } else {
  101. resolve(result.replace('\n', ''));
  102. }
  103. });
  104. });
  105. }