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.
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/)
# 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.
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
### Create new translation

View File

@ -5,13 +5,13 @@
const path = require('path');
const fs = require('fs');
const readline = require('readline');
const { spawn } = require('child_process');
const webpack = require('webpack');
const minifyCss = require('./minifyCss');
const serverConfig = require('../webpack.config.server.js');
const clientConfig = require('../webpack.config.client.js');
const { getAllAvailableLocals } = clientConfig;
let langs = 'all';
let doBuildServer = false;
@ -46,6 +46,88 @@ if (!doBuildServer && !doBuildClient) {
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) {
return new Promise((resolve, reject) => {
webpack(webpackConfig, (err, stats) => {
@ -156,13 +238,23 @@ async function buildProduction() {
if (langs !== 'all') {
avlangs = langs.split(',').map((l) => l.trim())
.filter((l) => avlangs.includes(l));
if (!avlangs.length) {
console.error(`ERROR: language ${langs} not available`);
process.exit(1);
return;
} else {
const { avlangs: goodLangs, badLangs } = await filterLackingLocals(avlangs, 50);
if (badLangs.length) {
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 = [];

View File

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