Skip to content

Commit

Permalink
feat: poeditor sync
Browse files Browse the repository at this point in the history
  • Loading branch information
aradzie committed Nov 25, 2024
1 parent 7e68fed commit d4535f7
Show file tree
Hide file tree
Showing 5 changed files with 165 additions and 85 deletions.
6 changes: 6 additions & 0 deletions docs/translations_report.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
# English

Translated: 417 messages, 5054 words

Untranslated: 0 messages, 0 words

# Arabic

Translated: 405 messages, 4943 words
Expand Down
16 changes: 16 additions & 0 deletions scripts/lib/intl-io.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { join } from "node:path";
import { rootDir } from "../root.js";

const outputDir = join(rootDir, "packages", "keybr-intl");

export function translationsPath(locale) {
return join(outputDir, `translations`, `${locale}.json`);
}

export function mergedTranslationsPath(locale) {
return join(outputDir, `translations`, `${locale}-merged.json`);
}

export function messagesPath(locale) {
return join(outputDir, `lib`, `messages`, `${locale}.json`);
}
38 changes: 38 additions & 0 deletions scripts/locale.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
export const defaultLocale = "en";

export const allLocales = [
defaultLocale,
"ar",
"bg",
"ca",
"cs",
"da",
"de",
"el",
"eo",
"es",
"et",
"fa",
"fr",
"he",
"hr",
"hu",
"id",
"it",
"ja",
"ko",
"ne",
"nl",
"pl",
"pt-br",
"pt-pt",
"ro",
"ru",
"sv",
"th",
"tr",
"uk",
"vi",
"zh-hans",
"zh-hant",
];
66 changes: 66 additions & 0 deletions scripts/poeditor-pull.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import { join } from "node:path";
import { config } from "dotenv";
import { readJsonSync, writeJsonSync } from "./lib/fs-json.js";
import { translationsPath } from "./lib/intl-io.js";
import { allLocales, defaultLocale } from "./locale.js";
import { rootDir } from "./root.js";

config({ path: join(rootDir, ".env") });

for (const locale of allLocales) {
if (locale === defaultLocale) {
continue;
}
await pullTranslations(locale);
}

async function pullTranslations(locale) {
const defaultTranslationsFile = translationsPath(defaultLocale);
const defaultTranslations = readJsonSync(defaultTranslationsFile);
const translationsFile = translationsPath(locale);
const translations = await downloadTranslations(locale);
writeJsonSync(
translationsFile,
remap(defaultTranslations, ([id, message]) => [
id,
translations[id] &&
translations[id] !== id &&
translations[id] !== message
? translations[id]
: undefined,
]),
);
}

async function downloadTranslations(locale) {
console.log(`Downloading translations ${locale}`);
if (locale === "pt-pt") {
locale = "pt";
}
const body = new FormData();
body.append("api_token", process.env["POEDITOR_TOKEN"]);
body.append("id", process.env["POEDITOR_PROJECT"]);
body.append("language", locale);
body.append("type", "key_value_json");
body.append("filters", "translated");
const res = await fetch("https://api.poeditor.com/v2/projects/export", {
method: "POST",
body: body,
});
if (!res.ok) {
throw new Error(res.statusText);
}
return await fetchJson((await res.json()).result.url);
}

async function fetchJson(url) {
const res = await fetch(url);
if (!res.ok) {
throw new Error(res.statusText);
}
return await res.json();
}

function remap(entries, callback) {
return Object.fromEntries(Object.entries(entries).map(callback));
}
124 changes: 39 additions & 85 deletions scripts/translate.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,49 +4,14 @@ import { compile, extract } from "@formatjs/cli-lib";
import { globSync } from "glob";
import { readJsonSync, writeJsonSync } from "./lib/fs-json.js";
import { messageIdHash } from "./lib/intl.js";
import {
mergedTranslationsPath,
messagesPath,
translationsPath,
} from "./lib/intl-io.js";
import { allLocales, defaultLocale } from "./locale.js";
import { findPackages, rootDir } from "./root.js";

const outputDir = join(rootDir, "packages", "keybr-intl");

const defaultLocale = "en";

const allLocales = [
defaultLocale,
"ar",
"bg",
"ca",
"cs",
"da",
"de",
"el",
"eo",
"es",
"et",
"fa",
"fr",
"he",
"hr",
"hu",
"id",
"it",
"ja",
"ko",
"ne",
"nl",
"pl",
"pt-br",
"pt-pt",
"ro",
"ru",
"sv",
"th",
"tr",
"uk",
"vi",
"zh-hans",
"zh-hant",
];

function findSourceFiles() {
const files = [];
for (const packageDirectory of findPackages()) {
Expand Down Expand Up @@ -80,35 +45,25 @@ async function extractTranslations() {
);
}

async function syncTranslations(report) {
async function syncTranslations() {
const defaultTranslationsFile = translationsPath(defaultLocale);
const defaultTranslations = readJsonSync(defaultTranslationsFile);
for (const locale of allLocales) {
if (locale === defaultLocale) {
continue;
}
const localeReport = (report[locale] = {
translated: [],
untranslated: [],
});
const translationsFile = translationsPath(locale);
const translations = readJsonSync(translationsFile);
writeJsonSync(
translationsFile,
remap(defaultTranslations, ([id, message]) => {
const translatedMessage =
translations[id] !== "" &&
translations[id] !== id &&
translations[id] !== message
? translations[id]
: undefined;
if (translatedMessage != null) {
localeReport.translated.push([id, message]);
} else if (!/\{[a-z]+\}/.test(message)) {
localeReport.untranslated.push([id, message]);
}
return [id, translatedMessage];
}),
remap(defaultTranslations, ([id, message]) => [
id,
translations[id] &&
translations[id] !== id &&
translations[id] !== message
? translations[id]
: undefined,
]),
);
}
}
Expand All @@ -134,7 +89,7 @@ async function compileMessages() {
mergedTranslationsFile,
remap(defaultTranslations, ([id, message]) => [
id,
translations[id] ?? message,
translations[id] || message,
]),
);
const messagesFile = messagesPath(locale);
Expand All @@ -148,7 +103,25 @@ async function compileMessages() {
}
}

async function writeReport(report) {
async function writeReport() {
const report = {};
const defaultTranslationsFile = translationsPath(defaultLocale);
const defaultTranslations = readJsonSync(defaultTranslationsFile);
for (const locale of allLocales) {
const translationsFile = translationsPath(locale);
const translations = readJsonSync(translationsFile);
const localeReport = (report[locale] = {
translated: [],
untranslated: [],
});
for (const [id, message] of Object.entries(defaultTranslations)) {
if (translations[id]) {
localeReport.translated.push([id, message]);
} else if (!/\{[a-z]+\}/.test(message)) {
localeReport.untranslated.push([id, message]);
}
}
}
const languageName = new Intl.DisplayNames("en", { type: "language" });
const countWords = (count, [id, message]) =>
count +
Expand Down Expand Up @@ -195,30 +168,11 @@ async function writeReport(report) {
);
}

async function run() {
const report = {};
await extractTranslations();
await syncTranslations(report);
await compileMessages();
await writeReport(report);
}

function remap(entries, callback) {
return Object.fromEntries(Object.entries(entries).map(callback));
}

function translationsPath(locale) {
return join(outputDir, `translations`, `${locale}.json`);
}

function mergedTranslationsPath(locale) {
return join(outputDir, `translations`, `${locale}-merged.json`);
}

function messagesPath(locale) {
return join(outputDir, `lib`, `messages`, `${locale}.json`);
}

run().catch((err) => {
console.error(err);
});
await extractTranslations();
await syncTranslations();
await compileMessages();
await writeReport();

0 comments on commit d4535f7

Please sign in to comment.