Files
learnGitBranching-mirror/scripts/extract-translation-template.js
Kovács PéterandClaude Sonnet 4.6 8c3e33e30c Add Hungarian (hu_HU) i18n support
- Register hu_HU locale in LocaleStore (langLocaleMap + headerLocaleMap)
- Add Magyar language button to IntlHelperBarView
- Translate all 104 UI strings in strings.js
- Translate name/hint/startDialog for all 34 levels across intro, rampup,
  mixed, advanced, rebase, and remote sequences
- Add scripts/validate-locale.js to check translation completeness
- Add scripts/extract-translation-template.js for contributor workflow
- Add TRANSLATING.md contributor guide with step-by-step instructions

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-20 08:52:50 +01:00

133 lines
4.0 KiB
JavaScript

#!/usr/bin/env node
'use strict';
/**
* Translation template extractor for learnGitBranching
*
* Generates a JSON template with all translatable strings and an empty target
* locale field for contributors to fill in.
*
* Usage: node scripts/extract-translation-template.js <locale> > template.json
* Example: node scripts/extract-translation-template.js hu_HU > template_hu.json
*
* After filling in the JSON, use the companion import script:
* node scripts/import-translation.js hu_HU template_hu.json
*/
const fs = require('fs');
const path = require('path');
const targetLocale = process.argv[2];
if (!targetLocale) {
console.error('Usage: node scripts/extract-translation-template.js <locale>');
console.error('Example: node scripts/extract-translation-template.js hu_HU');
process.exit(1);
}
const ROOT = path.join(__dirname, '..');
// ── 1. Extract UI strings ────────────────────────────────────────────────────
const stringsPath = path.join(ROOT, 'src/js/intl/strings.js');
const stringsSource = fs.readFileSync(stringsPath, 'utf8');
let strings;
try {
const m = { exports: {} };
new Function('exports', stringsSource)(m.exports);
strings = m.exports.strings || m.exports;
} catch (e) {
strings = require(stringsPath).strings || require(stringsPath);
}
const uiStrings = {};
for (const [key, entry] of Object.entries(strings)) {
uiStrings[key] = {
__desc__: entry.__desc__ || '',
en_US: entry.en_US || '',
[targetLocale]: entry[targetLocale] || '',
};
}
// ── 2. Extract level strings ─────────────────────────────────────────────────
const levelDirs = [
'src/levels/intro',
'src/levels/rampup',
'src/levels/move',
'src/levels/mixed',
'src/levels/advanced',
'src/levels/rebase',
'src/levels/remote',
'src/levels/remoteAdvanced',
];
const levels = {};
function extractLevel(filePath) {
const relPath = path.relative(ROOT, filePath).replace(/\\/g, '/');
let level;
try {
delete require.cache[require.resolve(filePath)];
level = require(filePath);
} catch (e) {
process.stderr.write(`WARN: Could not parse ${relPath}: ${e.message}\n`);
return;
}
if (!level || typeof level !== 'object') return;
const entry = { file: relPath };
if (level.name && typeof level.name === 'object') {
entry.name = {
en_US: level.name.en_US || '',
[targetLocale]: level.name[targetLocale] || '',
};
}
if (level.hint && typeof level.hint === 'object') {
entry.hint = {
en_US: level.hint.en_US || '',
[targetLocale]: level.hint[targetLocale] || '',
};
}
if (level.startDialog && typeof level.startDialog === 'object') {
entry.startDialog = {
en_US: level.startDialog.en_US || null,
[targetLocale]: level.startDialog[targetLocale] || null,
};
}
levels[relPath] = entry;
}
for (const dir of levelDirs) {
const dirPath = path.join(ROOT, dir);
if (!fs.existsSync(dirPath)) continue;
const files = fs.readdirSync(dirPath).filter(f => f.endsWith('.js') && f !== 'index.js');
for (const file of files) {
extractLevel(path.join(dirPath, file));
}
}
// ── 3. Output JSON template ──────────────────────────────────────────────────
const template = {
_meta: {
targetLocale,
generatedAt: new Date().toISOString(),
instructions: [
`Fill in all empty "${targetLocale}" fields with translations.`,
'Keep git command names in English (commit, branch, merge, rebase, etc.).',
'Keep markdown formatting intact (## headers, *bold*, `code`, etc.).',
'Keep placeholder variables like {nextLevel}, {branch}, etc. unchanged.',
'After filling in, run: node scripts/import-translation.js ' + targetLocale + ' <this-file>',
],
},
uiStrings,
levels,
};
process.stdout.write(JSON.stringify(template, null, 2) + '\n');