mirror of
https://github.com/Termix-SSH/Termix.git
synced 2026-10-28 06:05:24 +00:00
fix: crowdin sync and pretranslate for plugin locales, run plugin tests on release
This commit is contained in:
1 parent
1c4b057fd8
commit
f8edb5f299
5 files changed
+72
-30
No files matched your search
@@ -51,7 +51,7 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
CROWDIN_API_TOKEN: ${{ secrets.CROWDIN_API_KEY }}
|
CROWDIN_API_TOKEN: ${{ secrets.CROWDIN_API_KEY }}
|
||||||
|
|
||||||
- name: Machine pre-translate untranslated strings
|
- name: Pre-translate untranslated strings
|
||||||
env:
|
env:
|
||||||
CROWDIN_API_KEY: ${{ secrets.CROWDIN_API_KEY }}
|
CROWDIN_API_KEY: ${{ secrets.CROWDIN_API_KEY }}
|
||||||
run: node scripts/crowdin-pretranslate.cjs
|
run: node scripts/crowdin-pretranslate.cjs
|
||||||
@@ -74,7 +74,7 @@ jobs:
|
|||||||
git config user.name "LukeGus"
|
git config user.name "LukeGus"
|
||||||
git config user.email "bugattiguy527@gmail.com"
|
git config user.email "bugattiguy527@gmail.com"
|
||||||
|
|
||||||
git add src/ui/locales/translated
|
git add src/ui/locales/translated plugins/*/locales/translated
|
||||||
if git diff --cached --quiet; then
|
if git diff --cached --quiet; then
|
||||||
echo "No translation changes to commit."
|
echo "No translation changes to commit."
|
||||||
exit 0
|
exit 0
|
||||||
|
|||||||
@@ -102,8 +102,9 @@ jobs:
|
|||||||
|
|
||||||
- name: Lint and format
|
- name: Lint and format
|
||||||
run: |
|
run: |
|
||||||
npm run lint:fix || true
|
npm run lint:fix
|
||||||
npm run format
|
npm run format
|
||||||
|
npm run lint
|
||||||
|
|
||||||
# The plugin boot tests load the built bundles.
|
# The plugin boot tests load the built bundles.
|
||||||
- name: Build plugins
|
- name: Build plugins
|
||||||
@@ -112,6 +113,9 @@ jobs:
|
|||||||
- name: Run unit tests
|
- name: Run unit tests
|
||||||
run: npm run test
|
run: npm run test
|
||||||
|
|
||||||
|
- name: Run plugin tests
|
||||||
|
run: npm run test:plugins
|
||||||
|
|
||||||
- name: Sync version
|
- name: Sync version
|
||||||
run: node scripts/sync-version.cjs --version "${{ needs.prep.outputs.version }}"
|
run: node scripts/sync-version.cjs --version "${{ needs.prep.outputs.version }}"
|
||||||
|
|
||||||
@@ -184,7 +188,7 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
CROWDIN_API_TOKEN: ${{ secrets.CROWDIN_API_KEY }}
|
CROWDIN_API_TOKEN: ${{ secrets.CROWDIN_API_KEY }}
|
||||||
|
|
||||||
- name: Machine pre-translate untranslated strings
|
- name: Pre-translate untranslated strings
|
||||||
env:
|
env:
|
||||||
CROWDIN_API_KEY: ${{ secrets.CROWDIN_API_KEY }}
|
CROWDIN_API_KEY: ${{ secrets.CROWDIN_API_KEY }}
|
||||||
run: node scripts/crowdin-pretranslate.cjs
|
run: node scripts/crowdin-pretranslate.cjs
|
||||||
@@ -207,7 +211,7 @@ jobs:
|
|||||||
git config user.name "LukeGus"
|
git config user.name "LukeGus"
|
||||||
git config user.email "bugattiguy527@gmail.com"
|
git config user.email "bugattiguy527@gmail.com"
|
||||||
|
|
||||||
git add src/ui/locales/translated
|
git add src/ui/locales/translated plugins/*/locales/translated
|
||||||
if git diff --cached --quiet; then
|
if git diff --cached --quiet; then
|
||||||
echo "No translation changes to commit."
|
echo "No translation changes to commit."
|
||||||
exit 0
|
exit 0
|
||||||
|
|||||||
+4
-1
@@ -1,8 +1,11 @@
|
|||||||
project_id: "858252"
|
project_id: "858252"
|
||||||
api_token: "env:CROWDIN_API_TOKEN"
|
api_token: "env:CROWDIN_API_TOKEN"
|
||||||
|
preserve_hierarchy: true
|
||||||
|
|
||||||
files:
|
files:
|
||||||
|
# Core has always lived at /en.json in Crowdin; moving it would orphan its translations.
|
||||||
- source: /src/ui/locales/en.json
|
- source: /src/ui/locales/en.json
|
||||||
|
dest: /en.json
|
||||||
translation: /src/ui/locales/translated/%locale_with_underscore%.json
|
translation: /src/ui/locales/translated/%locale_with_underscore%.json
|
||||||
- source: /plugins/*/locales/en.json
|
- source: /plugins/*/locales/en.json
|
||||||
translation: /plugins/**/locales/translated/%locale_with_underscore%.json
|
translation: /%original_path%/translated/%locale_with_underscore%.json
|
||||||
@@ -52,14 +52,20 @@ async function resolveProjectId() {
|
|||||||
return { id: match.id, targetLanguageIds: match.targetLanguageIds || [] };
|
return { id: match.id, targetLanguageIds: match.targetLanguageIds || [] };
|
||||||
}
|
}
|
||||||
|
|
||||||
async function resolveFileId(projectId) {
|
// Core is /en.json and each plugin is /plugins/<id>/locales/en.json.
|
||||||
const files = await paged(`/projects/${projectId}/files`);
|
function isSourceFile(file) {
|
||||||
const match = files.find(
|
return (
|
||||||
(f) => f.name === SOURCE_FILE || f.path === `/${SOURCE_FILE}`,
|
file.path === `/${SOURCE_FILE}` ||
|
||||||
|
/^\/plugins\/[^/]+\/locales\/en\.json$/.test(file.path || "")
|
||||||
);
|
);
|
||||||
if (!match)
|
}
|
||||||
throw new Error(`source file "${SOURCE_FILE}" not found in project`);
|
|
||||||
return match.id;
|
async function resolveFileIds(projectId) {
|
||||||
|
const files = await paged(`/projects/${projectId}/files`);
|
||||||
|
const ids = files.filter(isSourceFile).map((f) => f.id);
|
||||||
|
if (ids.length === 0)
|
||||||
|
throw new Error(`no "${SOURCE_FILE}" source files found in project`);
|
||||||
|
return ids;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function pollPreTranslation(projectId, preTranslationId) {
|
async function pollPreTranslation(projectId, preTranslationId) {
|
||||||
@@ -84,31 +90,35 @@ async function main() {
|
|||||||
throw new Error("project has no target languages configured");
|
throw new Error("project has no target languages configured");
|
||||||
}
|
}
|
||||||
|
|
||||||
const fileId = await resolveFileId(projectId);
|
const fileIds = await resolveFileIds(projectId);
|
||||||
|
|
||||||
console.log(
|
console.log(
|
||||||
`Pre-translating project ${projectId}, file ${fileId}, ${targetLanguageIds.length} languages via MT engine ${ENGINE_ID}`,
|
`Pre-translating project ${projectId}, ${fileIds.length} files, ${targetLanguageIds.length} languages`,
|
||||||
);
|
);
|
||||||
|
|
||||||
const { data } = await request(
|
// Translation memory first so strings that moved between files keep their
|
||||||
"POST",
|
// existing translations, then machine translation for whatever is left.
|
||||||
`/projects/${projectId}/pre-translations`,
|
const passes = [
|
||||||
{
|
{ method: "tm", translateUntranslatedOnly: true },
|
||||||
languageIds: targetLanguageIds,
|
{ method: "mt", engineId: ENGINE_ID, scope: "untranslated" },
|
||||||
fileIds: [fileId],
|
];
|
||||||
method: "mt",
|
for (const pass of passes) {
|
||||||
engineId: ENGINE_ID,
|
const { data } = await request(
|
||||||
scope: "untranslated",
|
"POST",
|
||||||
},
|
`/projects/${projectId}/pre-translations`,
|
||||||
);
|
{ languageIds: targetLanguageIds, fileIds, ...pass },
|
||||||
|
);
|
||||||
const result = await pollPreTranslation(projectId, data.identifier);
|
const result = await pollPreTranslation(projectId, data.identifier);
|
||||||
console.log(`Pre-translation finished (${result.progress}%)`);
|
console.log(
|
||||||
|
`${pass.method} pre-translation finished (${result.progress}%)`,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
resolveProjectId,
|
resolveProjectId,
|
||||||
resolveFileId,
|
resolveFileIds,
|
||||||
|
isSourceFile,
|
||||||
pollPreTranslation,
|
pollPreTranslation,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
import { describe, expect, it } from "vitest";
|
||||||
|
import { createRequire } from "node:module";
|
||||||
|
|
||||||
|
const require = createRequire(import.meta.url);
|
||||||
|
const { isSourceFile } = require("./crowdin-pretranslate.cjs") as {
|
||||||
|
isSourceFile: (file: { path?: string }) => boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
describe("isSourceFile", () => {
|
||||||
|
it("matches the core and plugin source files", () => {
|
||||||
|
expect(isSourceFile({ path: "/en.json" })).toBe(true);
|
||||||
|
expect(isSourceFile({ path: "/plugins/acme-ssl/locales/en.json" })).toBe(
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("skips anything else", () => {
|
||||||
|
expect(isSourceFile({ path: "/src/ui/locales/en.json" })).toBe(false);
|
||||||
|
expect(isSourceFile({ path: "/plugins/a/b/locales/en.json" })).toBe(false);
|
||||||
|
expect(isSourceFile({ path: "/plugins/acme-ssl/locales/de.json" })).toBe(
|
||||||
|
false,
|
||||||
|
);
|
||||||
|
expect(isSourceFile({})).toBe(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
Reference in new issue
Block a user