chore: bump version to 1.14.3, fix translations and cleanup i18n
All checks were successful
Deploy to Production / deploy (push) Successful in 16s
All checks were successful
Deploy to Production / deploy (push) Successful in 16s
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "vue-nonograms-solid",
|
||||
"version": "1.14.2",
|
||||
"version": "1.14.3",
|
||||
"homepage": "https://nonograms.7u.pl/",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
|
||||
@@ -486,8 +486,8 @@ onUnmounted(() => {
|
||||
max="99"
|
||||
/>
|
||||
<div class="threshold-preview">
|
||||
<span>Low Density</span>
|
||||
<span>High Density</span>
|
||||
<span>{{ t('image.lowDensity') }}</span>
|
||||
<span>{{ t('image.highDensity') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -49,6 +49,8 @@ const messages = {
|
||||
'image.calculating': 'Obliczanie...',
|
||||
'image.calculatingSolvability': 'Obliczanie rozwiązywalności...',
|
||||
'image.create': 'STWÓRZ NONOGRAM',
|
||||
'image.lowDensity': 'Niska gęstość',
|
||||
'image.highDensity': 'Wysoka gęstość',
|
||||
'difficulty.easy': 'Łatwy',
|
||||
'difficulty.medium': 'Średni',
|
||||
'difficulty.hard': 'Trudny',
|
||||
@@ -229,10 +231,31 @@ const messages = {
|
||||
'custom.sizeError': 'Size must be between 5 and 80!',
|
||||
'custom.fillRate': 'Fill Rate',
|
||||
'custom.difficulty': 'Difficulty',
|
||||
'image.title': 'Import Image',
|
||||
'image.drop': 'Drag image here',
|
||||
'image.select': 'Select File',
|
||||
'image.camera': 'Take Photo',
|
||||
'image.capture': 'Capture',
|
||||
'image.switch': 'Switch Camera',
|
||||
'image.cameraError': 'Cannot access camera',
|
||||
'image.change': 'Change Image',
|
||||
'image.size': 'Grid Size',
|
||||
'image.threshold': 'Threshold',
|
||||
'image.solvability': 'Solvability',
|
||||
'image.warning': 'This image might require guessing!',
|
||||
'image.difficulty': 'Difficulty',
|
||||
'image.calculating': 'Calculating...',
|
||||
'image.calculatingSolvability': 'Calculating solvability...',
|
||||
'image.create': 'CREATE NONOGRAM',
|
||||
'image.lowDensity': 'Low Density',
|
||||
'image.highDensity': 'High Density',
|
||||
'difficulty.easy': 'Easy',
|
||||
'difficulty.medium': 'Medium',
|
||||
'difficulty.hard': 'Hard',
|
||||
'difficulty.harder': 'Harder',
|
||||
'difficulty.hardest': 'Hardest',
|
||||
'difficulty.extreme': 'Extreme',
|
||||
'difficulty.unknown': 'Unknown',
|
||||
'win.title': 'CONGRATULATIONS!',
|
||||
'win.message': 'You solved the puzzle!',
|
||||
'win.time': 'Time:',
|
||||
@@ -404,10 +427,31 @@ const messages = {
|
||||
'custom.sizeError': '尺寸必须在 5 到 80 之间!',
|
||||
'custom.fillRate': '填充率',
|
||||
'custom.difficulty': '难度',
|
||||
'image.title': 'IMPORT IMAGE',
|
||||
'image.drop': 'Drag image here',
|
||||
'image.select': 'Select File',
|
||||
'image.camera': 'Take Photo',
|
||||
'image.capture': 'Capture',
|
||||
'image.switch': 'Switch Camera',
|
||||
'image.cameraError': 'Cannot access camera',
|
||||
'image.change': 'Change Image',
|
||||
'image.size': 'Grid Size',
|
||||
'image.threshold': 'Threshold',
|
||||
'image.solvability': 'Solvability',
|
||||
'image.warning': 'This image might require guessing!',
|
||||
'image.difficulty': 'Difficulty',
|
||||
'image.calculating': 'Calculating...',
|
||||
'image.calculatingSolvability': 'Calculating solvability...',
|
||||
'image.create': 'CREATE NONOGRAM',
|
||||
'image.lowDensity': 'Low Density',
|
||||
'image.highDensity': 'High Density',
|
||||
'difficulty.easy': '简单',
|
||||
'difficulty.medium': '中等',
|
||||
'difficulty.hard': '困难',
|
||||
'difficulty.harder': '较难',
|
||||
'difficulty.hardest': '最难',
|
||||
'difficulty.extreme': '极限',
|
||||
'difficulty.unknown': '未知',
|
||||
'win.title': '恭喜!',
|
||||
'win.message': '你解开了谜题!',
|
||||
'win.time': '时间:',
|
||||
@@ -462,20 +506,6 @@ const messages = {
|
||||
'simulation.table.density': '密度',
|
||||
'simulation.table.solved': '已解(逻辑)',
|
||||
'simulation.empty': '点击开始运行蒙特卡罗模拟',
|
||||
'custom.simulationHelp': 'How is this calculated?',
|
||||
'custom.hideMap': 'Hide difficulty map',
|
||||
'custom.showMap': 'Show difficulty map',
|
||||
'simulation.title': 'Difficulty Simulation',
|
||||
'simulation.status.ready': 'Ready',
|
||||
'simulation.status.stopped': 'Stopped',
|
||||
'simulation.status.completed': 'Completed',
|
||||
'simulation.status.simulating': 'Simulating {size}x{size} @ {density}%',
|
||||
'simulation.start': 'Start Simulation',
|
||||
'simulation.stop': 'Stop',
|
||||
'simulation.table.size': 'Size',
|
||||
'simulation.table.density': 'Density',
|
||||
'simulation.table.solved': 'Solved (Logic)',
|
||||
'simulation.empty': 'Press Start to run Monte Carlo simulation',
|
||||
|
||||
'language.de': 'German',
|
||||
'language.it': 'Italian',
|
||||
@@ -627,34 +657,8 @@ const messages = {
|
||||
'language.searchPlaceholder': '輸入語言名稱...',
|
||||
'nav.newGame': '新遊戲',
|
||||
'nav.guide': '指南',
|
||||
'custom.simulationHelp': 'How is this calculated?',
|
||||
'custom.hideMap': 'Hide difficulty map',
|
||||
'custom.showMap': 'Show difficulty map',
|
||||
'simulation.title': 'Difficulty Simulation',
|
||||
'simulation.status.ready': 'Ready',
|
||||
'simulation.status.stopped': 'Stopped',
|
||||
'simulation.status.completed': 'Completed',
|
||||
'simulation.status.simulating': 'Simulating {size}x{size} @ {density}%',
|
||||
'simulation.start': 'Start Simulation',
|
||||
'simulation.stop': 'Stop',
|
||||
'simulation.table.size': 'Size',
|
||||
'simulation.table.density': 'Density',
|
||||
'simulation.table.solved': 'Solved (Logic)',
|
||||
'simulation.empty': 'Press Start to run Monte Carlo simulation',
|
||||
'custom.simulationHelp': 'How is this calculated?',
|
||||
'custom.hideMap': 'Hide difficulty map',
|
||||
'custom.showMap': 'Show difficulty map',
|
||||
'simulation.title': 'Difficulty Simulation',
|
||||
'simulation.status.ready': 'Ready',
|
||||
'simulation.status.stopped': 'Stopped',
|
||||
'simulation.status.completed': 'Completed',
|
||||
'simulation.status.simulating': 'Simulating {size}x{size} @ {density}%',
|
||||
'simulation.start': 'Start Simulation',
|
||||
'simulation.stop': 'Stop',
|
||||
'simulation.table.size': 'Size',
|
||||
'simulation.table.density': 'Density',
|
||||
'simulation.table.solved': 'Solved (Logic)',
|
||||
'simulation.empty': 'Press Start to run Monte Carlo simulation',
|
||||
|
||||
|
||||
|
||||
'language.de': 'German',
|
||||
'language.it': 'Italian',
|
||||
@@ -819,20 +823,7 @@ const messages = {
|
||||
'simulation.table.density': 'घनत्व',
|
||||
'simulation.table.solved': 'हल (तर्क)',
|
||||
'simulation.empty': 'मोंटे कार्लो सिमुलेशन चलाने के लिए स्टार्ट दबाएँ',
|
||||
'custom.simulationHelp': 'How is this calculated?',
|
||||
'custom.hideMap': 'Hide difficulty map',
|
||||
'custom.showMap': 'Show difficulty map',
|
||||
'simulation.title': 'Difficulty Simulation',
|
||||
'simulation.status.ready': 'Ready',
|
||||
'simulation.status.stopped': 'Stopped',
|
||||
'simulation.status.completed': 'Completed',
|
||||
'simulation.status.simulating': 'Simulating {size}x{size} @ {density}%',
|
||||
'simulation.start': 'Start Simulation',
|
||||
'simulation.stop': 'Stop',
|
||||
'simulation.table.size': 'Size',
|
||||
'simulation.table.density': 'Density',
|
||||
'simulation.table.solved': 'Solved (Logic)',
|
||||
'simulation.empty': 'Press Start to run Monte Carlo simulation',
|
||||
|
||||
|
||||
'language.de': 'German',
|
||||
'language.it': 'Italian',
|
||||
@@ -1006,20 +997,7 @@ const messages = {
|
||||
'simulation.table.density': 'Densidad',
|
||||
'simulation.table.solved': 'Resuelto (Lógica)',
|
||||
'simulation.empty': 'Pulsa Iniciar para ejecutar la simulación Monte Carlo',
|
||||
'custom.simulationHelp': 'How is this calculated?',
|
||||
'custom.hideMap': 'Hide difficulty map',
|
||||
'custom.showMap': 'Show difficulty map',
|
||||
'simulation.title': 'Difficulty Simulation',
|
||||
'simulation.status.ready': 'Ready',
|
||||
'simulation.status.stopped': 'Stopped',
|
||||
'simulation.status.completed': 'Completed',
|
||||
'simulation.status.simulating': 'Simulating {size}x{size} @ {density}%',
|
||||
'simulation.start': 'Start Simulation',
|
||||
'simulation.stop': 'Stop',
|
||||
'simulation.table.size': 'Size',
|
||||
'simulation.table.density': 'Density',
|
||||
'simulation.table.solved': 'Solved (Logic)',
|
||||
'simulation.empty': 'Press Start to run Monte Carlo simulation',
|
||||
|
||||
|
||||
'language.de': 'German',
|
||||
'language.it': 'Italian',
|
||||
|
||||
107
verify_i18n.js
Normal file
107
verify_i18n.js
Normal file
@@ -0,0 +1,107 @@
|
||||
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import { fileURLToPath } from 'url';
|
||||
import { execSync } from 'child_process';
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = path.dirname(__filename);
|
||||
|
||||
// 1. Parse useI18n.js to get keys
|
||||
const i18nPath = path.join(__dirname, 'src/composables/useI18n.js');
|
||||
const i18nContent = fs.readFileSync(i18nPath, 'utf8');
|
||||
|
||||
function extractKeys(lang) {
|
||||
// Find start of lang block: " en: {"
|
||||
const startRegex = new RegExp(`\\s+${lang}:\\s*\\{`);
|
||||
const startMatch = i18nContent.match(startRegex);
|
||||
if (!startMatch) return new Set();
|
||||
|
||||
const startIndex = startMatch.index + startMatch[0].length;
|
||||
let braceCount = 1;
|
||||
let inString = false;
|
||||
let stringChar = '';
|
||||
let endIndex = -1;
|
||||
|
||||
for (let i = startIndex; i < i18nContent.length; i++) {
|
||||
const char = i18nContent[i];
|
||||
|
||||
if (inString) {
|
||||
if (char === stringChar && i18nContent[i-1] !== '\\') {
|
||||
inString = false;
|
||||
}
|
||||
} else {
|
||||
if (char === "'" || char === '"' || char === '`') {
|
||||
inString = true;
|
||||
stringChar = char;
|
||||
} else if (char === '{') {
|
||||
braceCount++;
|
||||
} else if (char === '}') {
|
||||
braceCount--;
|
||||
if (braceCount === 0) {
|
||||
endIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (endIndex === -1) return new Set();
|
||||
|
||||
const block = i18nContent.substring(startIndex, endIndex);
|
||||
const keys = new Set();
|
||||
const keyRegex = /['"]([\w.-]+)['"]\s*:/g;
|
||||
let match;
|
||||
while ((match = keyRegex.exec(block)) !== null) {
|
||||
keys.add(match[1]);
|
||||
}
|
||||
return keys;
|
||||
}
|
||||
|
||||
const enKeys = extractKeys('en');
|
||||
console.log(`Found ${enKeys.size} keys in en block.`);
|
||||
|
||||
if (enKeys.has('image.title')) {
|
||||
console.log("'image.title' IS present in en block.");
|
||||
} else {
|
||||
console.log("'image.title' is MISSING in en block.");
|
||||
}
|
||||
|
||||
// 2. Scan src for usages
|
||||
try {
|
||||
const grepOutput = execSync(`grep -r "t(['\\"]" src | grep -v "node_modules"`, { encoding: 'utf8' });
|
||||
|
||||
const usedKeys = new Set();
|
||||
const usageRegex = /t\(['"]([\w.-]+)['"]/g;
|
||||
|
||||
const lines = grepOutput.split('\n');
|
||||
for (const line of lines) {
|
||||
let m;
|
||||
while ((m = usageRegex.exec(line)) !== null) {
|
||||
usedKeys.add(m[1]);
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`Found ${usedKeys.size} used keys in src.`);
|
||||
|
||||
// 3. Compare
|
||||
const missingKeys = [];
|
||||
for (const key of usedKeys) {
|
||||
// Skip dynamic keys or composed keys if any (heuristic)
|
||||
if (key.includes('${')) continue;
|
||||
|
||||
if (!enKeys.has(key)) {
|
||||
missingKeys.push(key);
|
||||
}
|
||||
}
|
||||
|
||||
if (missingKeys.length > 0) {
|
||||
console.log("Missing translations in en:");
|
||||
missingKeys.forEach(k => console.log(` - ${k}`));
|
||||
} else {
|
||||
console.log("No missing translations found in en.");
|
||||
}
|
||||
|
||||
} catch (e) {
|
||||
console.error("Error running grep:", e);
|
||||
}
|
||||
Reference in New Issue
Block a user