parse country code for language out of i18n/lccc.json

This commit is contained in:
HF 2024-03-09 12:51:02 +01:00
parent e7cf57ec1b
commit 48d92ce963
4 changed files with 104 additions and 26 deletions

View File

@ -2,6 +2,8 @@
The easiets way to help translate the game is with weblate. Simply use [hosted.weblate.org/projects/pixelplanet](https://hosted.weblate.org/projects/pixelplanet/). Feel free to ask in the Translation section in [our Discord](https://pixelplanet.fun/guilded) if you need help. The easiets way to help translate the game is with weblate. Simply use [hosted.weblate.org/projects/pixelplanet](https://hosted.weblate.org/projects/pixelplanet/). Feel free to ask in the Translation section in [our Discord](https://pixelplanet.fun/guilded) if you need help.
If a language code differs from the country code of a wanted flag, it can be defined in the `i18n/lccc.json` file. In example `{ "en": "gb" }` maps the english language to the flag of Great Britain.
[![Translation status](https://hosted.weblate.org/widget/pixelplanet/open-graph.png)](https://hosted.weblate.org/engage/pixelplanet/) [![Translation status](https://hosted.weblate.org/widget/pixelplanet/open-graph.png)](https://hosted.weblate.org/engage/pixelplanet/)
# Translating Offline # Translating Offline
@ -12,8 +14,6 @@ Translation files can be created out of the templates [template.pot](https://git
All translated languages get an own chat channel that just people who use this language can access. All translated languages get an own chat channel that just people who use this language can access.
If a language code differs from the country code of a wanted flag, it can be defined in the ssr filename, like `ssr-en-gb.po` would be the english language, with the flag of Great Britain.
## With poedit ## With poedit
### Create new translation ### Create new translation

View File

@ -5,13 +5,13 @@
const path = require('path'); const path = require('path');
const fs = require('fs'); const fs = require('fs');
const readline = require('readline');
const { spawn } = require('child_process'); const { spawn } = require('child_process');
const webpack = require('webpack'); const webpack = require('webpack');
const minifyCss = require('./minifyCss'); const minifyCss = require('./minifyCss');
const serverConfig = require('../webpack.config.server.js'); const serverConfig = require('../webpack.config.server.js');
const clientConfig = require('../webpack.config.client.js'); const clientConfig = require('../webpack.config.client.js');
const { getAllAvailableLocals } = clientConfig;
let langs = 'all'; let langs = 'all';
let doBuildServer = false; let doBuildServer = false;
@ -46,6 +46,88 @@ if (!doBuildServer && !doBuildClient) {
doBuildClient = true; doBuildClient = true;
} }
/*
* get available locals based on the files available in ../i18n
*/
function getAllAvailableLocals() {
const langDir = path.resolve(__dirname, '..', 'i18n');
const langs = fs.readdirSync(langDir)
.filter((e) => (e.endsWith('.po') && !e.startsWith('ssr')))
.map((l) => l.slice(0, -3));
langs.unshift('en');
return langs;
}
/*
* get amount of msgid and msgstr of po file
*/
function getPoFileStats(file) {
return new Promise((resolve) => {
const fileStream = fs.createReadStream(file);
const lineReader = readline.createInterface({
input: fileStream,
crlfDelay: Infinity,
});
let msgid = 0;
let msgstr = 0;
lineReader.on('line', (l) => {
l = l.trim();
if (l.endsWith('""')) {
return;
}
let seperator = l.indexOf(' ');
if (seperator === -1) {
seperator = l.indexOf('\t');
}
if (seperator === -1) {
return;
}
const tag = l.substring(0, seperator);
if (tag === 'msgid') {
msgid += 1;
} else if (tag === 'msgstr') {
msgstr += 1;
}
});
lineReader.on('close', (l) => {
resolve({ msgid, msgstr });
});
});
}
async function filterLackingLocals(langs, percentage) {
langs = langs.filter((l) => l !== 'en');
const promises = [];
const { msgid, msgstr } = await getPoFileStats(path.resolve(
__dirname, '..', 'i18n', `template.pot`,
));
const langStats = await Promise.all(langs
.map((l) => getPoFileStats(
path.resolve(__dirname, '..', 'i18n', `${l}.po`),
)));
const goodLangs = [ 'en' ];
const badLangs = [];
for (let i = 0; i < langs.length; i += 1) {
const lang = langs[i];
const stats = langStats[i];
const percent = Math.floor(stats.msgstr / msgid * 100);
if (percent >= percentage) {
goodLangs.push(lang);
} else {
console.log(`Lang ${lang} completion:`, percent, '%');
badLangs.push(lang);
}
}
return {
goodLangs,
badLangs,
};
}
function compile(webpackConfig) { function compile(webpackConfig) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
webpack(webpackConfig, (err, stats) => { webpack(webpackConfig, (err, stats) => {
@ -156,13 +238,23 @@ async function buildProduction() {
if (langs !== 'all') { if (langs !== 'all') {
avlangs = langs.split(',').map((l) => l.trim()) avlangs = langs.split(',').map((l) => l.trim())
.filter((l) => avlangs.includes(l)); .filter((l) => avlangs.includes(l));
if (!avlangs.length) { } else {
console.error(`ERROR: language ${langs} not available`); const { avlangs: goodLangs, badLangs } = await filterLackingLocals(avlangs, 50);
process.exit(1); if (badLangs.length) {
return; console.log(
'Skipping',
badLangs.length,
'locals because of low completition:',
badLangs,
);
} }
} }
console.log('Building locales:', avlangs); if (!avlangs.length) {
console.error(`ERROR: language ${langs} not available`);
process.exit(1);
return;
}
console.log('Building', avlangs.length, 'locales:', avlangs);
const promises = []; const promises = [];

View File

@ -6,6 +6,7 @@ import cookie from 'cookie';
import assetWatcher from './fsWatcher'; import assetWatcher from './fsWatcher';
import { getLangsOfJsAsset } from './assets'; import { getLangsOfJsAsset } from './assets';
import lccc from '../../i18n/lccc.json';
// eslint-disable-next-line max-len // eslint-disable-next-line max-len
const localeImports = require.context('../../i18n', false, /^\.[/\\]ssr-.+\.po$/); const localeImports = require.context('../../i18n', false, /^\.[/\\]ssr-.+\.po$/);
@ -32,16 +33,11 @@ function loadTtags() {
const file = langs[i]; const file = langs[i];
// ./ssr-de.po // ./ssr-de.po
let lang = file.replace('./ssr-', '').replace('.po', '').toLowerCase(); let lang = file.replace('./ssr-', '').replace('.po', '').toLowerCase();
let flag = lang;
/* /*
* in cases where the language code and country code differ, * In cases where the language code and country code differ,
* the country code can be given seperately in the file name * it can be mapped in i18n/lccc.json
* i.e.: ./ssr-en-gb.po
*/ */
const seperator = lang.indexOf('-'); let flag = lccc[lang] || lang;
if (seperator !== -1) {
[lang, flag] = lang.split('-');
}
if (jsLangs.includes(lang)) { if (jsLangs.includes(lang)) {
if (!ttags[lang]) { if (!ttags[lang]) {
const ttag = new TTag(); const ttag = new TTag();

View File

@ -183,13 +183,3 @@ module.exports = ({
}; };
} }
function getAllAvailableLocals() {
const langDir = path.resolve('i18n');
const langs = fs.readdirSync(langDir)
.filter((e) => (e.endsWith('.po') && !e.startsWith('ssr')))
.map((l) => l.slice(0, -3));
langs.unshift('en');
return langs;
}
module.exports.getAllAvailableLocals = getAllAvailableLocals;