1
0
mirror of https://github.com/laurent22/joplin.git synced 2024-12-24 10:27:10 +02:00
joplin/packages/tools/utils/translation.ts

85 lines
2.8 KiB
TypeScript

import { execCommand, isMac } from '../tool-utils';
import { existsSync, readFile } from 'fs-extra';
const gettextParser = require('gettext-parser');
export interface TranslationStatus {
locale?: string;
languageName?: string;
translatorName: string;
percentDone: number;
untranslatedCount: number;
pluralForms?: string;
}
export type Translations = Record<string, string[]>;
export const removePoHeaderDate = async (filePath: string) => {
let sedPrefix = 'sed -i';
if (isMac()) sedPrefix += ' ""'; // Note: on macOS it has to be 'sed -i ""' (BSD quirk)
await execCommand(`${sedPrefix} -e'/POT-Creation-Date:/d' "${filePath}"`);
await execCommand(`${sedPrefix} -e'/PO-Revision-Date:/d' "${filePath}"`);
};
export const translationExecutablePath = (file: string) => {
const potentialPaths = [
'/usr/local/opt/gettext/bin/',
'/opt/local/bin/',
'/usr/local/bin/',
];
for (const path of potentialPaths) {
const pathFile = path + file;
if (existsSync(pathFile)) {
return pathFile;
}
}
throw new Error(`${file} could not be found. Please install via brew or MacPorts.\n`);
};
export const mergePotToPo = async (potFilePath: string, poFilePath: string) => {
let msgmergePath = 'msgmerge';
if (isMac()) msgmergePath = translationExecutablePath('msgmerge'); // Needs to have been installed with `brew install gettext`
const command = `${msgmergePath} -U "${poFilePath}" "${potFilePath}"`;
const result = await execCommand(command);
if (result && result.trim()) console.info(result.trim());
await removePoHeaderDate(poFilePath);
};
export const parsePoFile = async (filePath: string) => {
const content = await readFile(filePath);
return gettextParser.po.parse(content);
};
// Convert the gettext translations, as returned by `gettextParser.po.parse()`
// to a <string, string> map, with the English text on the left and the
// translation on the right. If a particular translation is missing, no entry
// will be returned. The caller should display the English text in this case.
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied
export const parseTranslations = (gettextTranslations: any) => {
const output: Translations = {};
// Translations are grouped by "msgctxt"
for (const msgctxt of Object.keys(gettextTranslations.translations)) {
const translations = gettextTranslations.translations[msgctxt];
for (const n in translations) {
if (!translations.hasOwnProperty(n)) continue;
if (n === '') continue;
const t = translations[n];
let translated: string[] = [];
if (t.comments && t.comments.flag && t.comments.flag.indexOf('fuzzy') >= 0) {
// Don't include fuzzy translations
} else {
translated = t['msgstr'];
}
if (translated.length) output[n] = translated;
}
}
return output;
};