Skip to content

Commit 178a28e

Browse files
authored
Merge pull request #16670 from ethereum/i18n-automation
poc: I18n automation
2 parents 53fe332 + 1565781 commit 178a28e

File tree

5 files changed

+1824
-0
lines changed

5 files changed

+1824
-0
lines changed
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
name: Import Crowdin AI Translations
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
file_limit:
7+
description: "Number of files to process (default: 100, use 1-10 for testing)"
8+
required: false
9+
default: "100"
10+
type: string
11+
target_languages:
12+
description: "Comma-separated Crowdin language codes (default: es-EM)"
13+
required: false
14+
default: "es-EM"
15+
type: string
16+
base_branch:
17+
description: "Base branch to create PR against (default: dev)"
18+
required: false
19+
default: "dev"
20+
type: string
21+
22+
jobs:
23+
import_translations:
24+
runs-on: ubuntu-latest
25+
steps:
26+
- name: Check out code
27+
uses: actions/checkout@v5
28+
29+
- name: Setup pnpm
30+
uses: pnpm/action-setup@v4
31+
32+
- name: Set up Node.js
33+
uses: actions/setup-node@v6
34+
with:
35+
node-version: 20
36+
cache: "pnpm"
37+
38+
- name: Install dependencies
39+
run: pnpm install
40+
41+
- name: Run Crowdin AI translation import
42+
run: npx ts-node -O '{"module":"commonjs"}' ./src/scripts/i18n/main.ts
43+
env:
44+
I18N_CROWDIN_API_KEY: ${{ secrets.CROWDIN_API_KEY }}
45+
I18N_GITHUB_API_KEY: ${{ secrets.I18N_GITHUB_TOKEN }}
46+
FILE_LIMIT: ${{ github.event.inputs.file_limit }}
47+
TARGET_LANGUAGES: ${{ github.event.inputs.target_languages }}
48+
BASE_BRANCH: ${{ github.event.inputs.base_branch }}
49+
GITHUB_REPOSITORY: ${{ github.repository }}
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
/**
2+
* Quick script to check translation status of a specific file in Crowdin
3+
*/
4+
5+
const CROWDIN_API_KEY = process.env.CROWDIN_TOKEN!
6+
const PROJECT_ID = 834930
7+
const FILE_ID = 17434 // organizing/index.md
8+
const LANGUAGE_ID = "es-EM"
9+
10+
const headers = {
11+
Authorization: `Bearer ${CROWDIN_API_KEY}`,
12+
"Content-Type": "application/json",
13+
}
14+
15+
async function checkTranslationProgress() {
16+
console.log("\n=== Checking Translation Progress ===")
17+
console.log(`File ID: ${FILE_ID}`)
18+
console.log(`Language: ${LANGUAGE_ID}`)
19+
20+
// Get translation progress for the file
21+
const url = `https://api.crowdin.com/api/v2/projects/${PROJECT_ID}/languages/${LANGUAGE_ID}/progress?fileIds=${FILE_ID}`
22+
23+
try {
24+
const res = await fetch(url, { headers })
25+
if (!res.ok) {
26+
const text = await res.text()
27+
throw new Error(`Failed to get progress (${res.status}): ${text}`)
28+
}
29+
30+
const json = await res.json()
31+
console.log("\nTranslation Progress:")
32+
console.log(JSON.stringify(json, null, 2))
33+
} catch (error) {
34+
console.error("Error:", error)
35+
}
36+
}
37+
38+
async function listStrings() {
39+
console.log("\n=== Listing Strings in File ===")
40+
41+
// Get strings from the file
42+
const url = `https://api.crowdin.com/api/v2/projects/${PROJECT_ID}/strings?fileId=${FILE_ID}&limit=10`
43+
44+
try {
45+
const res = await fetch(url, { headers })
46+
if (!res.ok) {
47+
const text = await res.text()
48+
throw new Error(`Failed to list strings (${res.status}): ${text}`)
49+
}
50+
51+
const json = await res.json()
52+
console.log(`\nFound ${json.data.length} strings (showing first 10):`)
53+
for (const item of json.data) {
54+
console.log(`\nString ID: ${item.data.id}`)
55+
console.log(`Text: "${item.data.text.substring(0, 100)}..."`)
56+
console.log(`Context: ${item.data.context || "none"}`)
57+
}
58+
} catch (error) {
59+
console.error("Error:", error)
60+
}
61+
}
62+
63+
async function checkStringTranslations() {
64+
console.log("\n=== Checking String Translations ===")
65+
66+
// First get a string ID
67+
const stringsUrl = `https://api.crowdin.com/api/v2/projects/${PROJECT_ID}/strings?fileId=${FILE_ID}&limit=1`
68+
69+
try {
70+
const stringsRes = await fetch(stringsUrl, { headers })
71+
if (!stringsRes.ok) {
72+
throw new Error(`Failed to get strings: ${stringsRes.status}`)
73+
}
74+
75+
const stringsJson = await stringsRes.json()
76+
if (stringsJson.data.length === 0) {
77+
console.log("❌ No strings found in file!")
78+
return
79+
}
80+
81+
const stringId = stringsJson.data[0].data.id
82+
console.log(`\nChecking translations for string ID: ${stringId}`)
83+
console.log(
84+
`String text: "${stringsJson.data[0].data.text.substring(0, 100)}..."`
85+
)
86+
87+
// Get translations for this string
88+
const translationsUrl = `https://api.crowdin.com/api/v2/projects/${PROJECT_ID}/translations?stringId=${stringId}&languageId=${LANGUAGE_ID}`
89+
const transRes = await fetch(translationsUrl, { headers })
90+
91+
if (!transRes.ok) {
92+
const text = await transRes.text()
93+
console.log(
94+
`\n⚠️ No translations found or error (${transRes.status}): ${text}`
95+
)
96+
return
97+
}
98+
99+
const transJson = await transRes.json()
100+
console.log(`\nTranslations found: ${transJson.data.length}`)
101+
if (transJson.data.length > 0) {
102+
console.log("First translation:")
103+
console.log(JSON.stringify(transJson.data[0].data, null, 2))
104+
} else {
105+
console.log("❌ String has NO translations in Spanish!")
106+
}
107+
} catch (error) {
108+
console.error("Error:", error)
109+
}
110+
}
111+
112+
async function main() {
113+
await checkTranslationProgress()
114+
await listStrings()
115+
await checkStringTranslations()
116+
}
117+
118+
main()

0 commit comments

Comments
 (0)