TranslationsToCsv outputs only translations keys used in code

This commit is contained in:
Martti Malmi 2023-02-03 22:43:10 +02:00
parent 8dc357dfc8
commit 6e1f531151
7 changed files with 32 additions and 33 deletions

View File

@ -47,6 +47,7 @@
"eslint-config-prettier": "^8.6.0", "eslint-config-prettier": "^8.6.0",
"eslint-plugin-prettier": "^4.2.1", "eslint-plugin-prettier": "^4.2.1",
"eslint-plugin-simple-import-sort": "^9.0.0", "eslint-plugin-simple-import-sort": "^9.0.0",
"glob": "^8.1.0",
"gun": "^0.2020.1238", "gun": "^0.2020.1238",
"jest": "^29.4.0", "jest": "^29.4.0",
"jest-preset-preact": "^4.0.5", "jest-preset-preact": "^4.0.5",

View File

@ -1,29 +1,35 @@
import fs from 'fs'; import fs from 'fs';
import glob from 'glob';
import { AVAILABLE_LANGUAGE_KEYS } from '../src/js/translations/Translation.mjs'; import { AVAILABLE_LANGUAGE_KEYS } from '../src/js/translations/Translation.mjs';
// Create a csv file where each row is a translation key and the column is the translation in different languages.
// The file is created in the current working directory.
// The file name is "translations.csv".
async function translationsToCsv() { async function translationsToCsv() {
let csv = ''; let csv = '';
let languages = []; let languages = [];
let translationKeys = []; let translationKeys = new Set();
let translations = {}; let translations = {};
for (let lang of AVAILABLE_LANGUAGE_KEYS) { for (let lang of AVAILABLE_LANGUAGE_KEYS) {
const translation = (await import(`../src/js/translations/${lang}.mjs`)).default; const translation = (await import(`../src/js/translations/${lang}.mjs`)).default;
translations[lang] = translation; translations[lang] = translation;
languages.push(lang); languages.push(lang);
for (let key in translation) {
if (translationKeys.indexOf(key) === -1) {
translationKeys.push(key);
}
}
} }
// Collect used translation keys from code
const files = glob.sync('../src/js/**/*.{js,jsx,ts,tsx}', { ignore: '../src/js/lib/**/*' });
files.forEach((file) => {
const content = fs.readFileSync(file, 'utf8');
const matches = content.match(/(^|[^a-zA-Z])t\(['"`]([^'"`]+)['"`]\)/g);
if (matches) {
matches.forEach((match) => {
const key = match.match(/(^|[^a-zA-Z])t\(['"`]([^'"`]+)['"`]\)/)[2];
translationKeys.add(key);
});
}
});
console.log('found', translationKeys.size, 'translation keys from', files.length, 'files');
languages.sort(); languages.sort();
translationKeys = Array.from(translationKeys);
translationKeys.sort(); translationKeys.sort();
// add language names to csv // add language names to csv
@ -54,22 +60,4 @@ async function translationsToCsv() {
console.log('wrote translations.csv'); console.log('wrote translations.csv');
} }
// convert the csv back to Translations.mjs in the same format as the original Translations.mjs file
function csvToTranslations() {
// TODO: work in progress
let csv = fs.readFileSync('translations.csv', 'utf8');
let lines = csv.split('\n');
let translations = {};
let languages = lines[0].split(',');
languages.shift();
for (let i = 1; i < lines.length; i++) {
let line = lines[i].split(',');
let key = line[0];
line.shift();
for (let j = 0; j < languages.length; j++) {
translations[key][languages[j]] = line[j] || null;
}
}
}
translationsToCsv(); translationsToCsv();

View File

@ -1,6 +1,5 @@
import { html } from 'htm/preact'; import { html } from 'htm/preact';
import iris from 'iris-lib'; import iris from 'iris-lib';
import { Link } from 'preact-router/match';
import logo from '../../assets/img/icon128.png'; import logo from '../../assets/img/icon128.png';
import Component from '../BaseComponent'; import Component from '../BaseComponent';

View File

@ -204,7 +204,7 @@ class Login extends Component {
id="show-existing-account-login" id="show-existing-account-login"
onClick={() => this.setState({ showSwitchAccount: true })} onClick={() => this.setState({ showSwitchAccount: true })}
> >
{t('Private key login')} {t('private_key_login')}
</a> </a>
</p> </p>
<p> <p>

View File

@ -44,7 +44,7 @@ class QRView extends Component {
render() { render() {
return ( return (
<> <>
<h2>{t('Show_or_scan_QR_code')}</h2> <h2>{t('show_or_scan_QR_code')}</h2>
<Button id="scan-chatlink-qr-btn" onClick={() => this.scanChatLinkQr()}> <Button id="scan-chatlink-qr-btn" onClick={() => this.scanChatLinkQr()}>
{t('scan_qr_code')} {t('scan_qr_code')}
</Button> </Button>

View File

@ -13,7 +13,7 @@ export default class AppearanceSettings extends Component {
return ( return (
<> <>
<div class="centered-container"> <div class="centered-container">
<h3>{t('Appearance')}</h3> <h3>{t('appearance')}</h3>
<p> <p>
<label for="colorScheme">{t('color_scheme')}</label> <label for="colorScheme">{t('color_scheme')}</label>
<select <select

View File

@ -5999,6 +5999,17 @@ glob@^8.0.3:
minimatch "^5.0.1" minimatch "^5.0.1"
once "^1.3.0" once "^1.3.0"
glob@^8.1.0:
version "8.1.0"
resolved "https://registry.yarnpkg.com/glob/-/glob-8.1.0.tgz#d388f656593ef708ee3e34640fdfb99a9fd1c33e"
integrity sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==
dependencies:
fs.realpath "^1.0.0"
inflight "^1.0.4"
inherits "2"
minimatch "^5.0.1"
once "^1.3.0"
global-dirs@^3.0.0: global-dirs@^3.0.0:
version "3.0.0" version "3.0.0"
resolved "https://registry.yarnpkg.com/global-dirs/-/global-dirs-3.0.0.tgz#70a76fe84ea315ab37b1f5576cbde7d48ef72686" resolved "https://registry.yarnpkg.com/global-dirs/-/global-dirs-3.0.0.tgz#70a76fe84ea315ab37b1f5576cbde7d48ef72686"