Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/feat/rf-1267-update-crowdin-wo…
Browse files Browse the repository at this point in the history
…rkflow-with-pre-translate' into next
  • Loading branch information
yeager-eren committed Feb 17, 2024
2 parents f9d4ce8 + 05c9beb commit be4b290
Show file tree
Hide file tree
Showing 5 changed files with 182 additions and 49 deletions.
13 changes: 0 additions & 13 deletions .github/workflows/checks.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,3 @@ jobs:
run: node ./scripts/check-conventional-commits/command.mjs
env:
REF: ${{ github.ref }}

localization:
if: ${{ github.base_ref == 'main' }}
uses: ./.github/workflows/crowdin.yml
needs:
- check
secrets:
CROWDIN_PROJECT_ID: ${{ secrets.CROWDIN_PROJECT_ID }}
CROWDIN_PERSONAL_TOKEN: ${{ secrets.CROWDIN_PERSONAL_TOKEN }}
PAT: ${{ secrets.PAT }}
with:
create_pull_request: false
localization_branch_name: ${{github.head_ref}}
44 changes: 23 additions & 21 deletions .github/workflows/crowdin.yml
Original file line number Diff line number Diff line change
@@ -1,15 +1,7 @@
name: Sync translations using Crowdin
env:
LOCALIZATION_BRANCH_NAME: 'l10n_crowdin_translations'

on:
workflow_dispatch:
inputs:
create_pull_request:
description: 'It requires pull request'
required: false
default: true
type: boolean

workflow_call:
secrets:
Expand All @@ -22,19 +14,14 @@ on:
PAT:
description: 'Add a PAT to secrets.'
required: true
inputs:
localization_branch_name:
description: 'Target branch name for new commit'
required: false
type: string
create_pull_request:
description: 'It requires pull request'
type: boolean
required: true

jobs:
crowdin:
runs-on: ubuntu-latest
env:
CROWDIN_PROJECT_ID: ${{ secrets.CROWDIN_PROJECT_ID }}
CROWDIN_PERSONAL_TOKEN: ${{ secrets.CROWDIN_PERSONAL_TOKEN }}
GITHUB_TOKEN: ${{ secrets.PAT }}
steps:
- uses: actions/checkout@v4
with:
Expand All @@ -47,21 +34,36 @@ jobs:
- name: Extract new source
run: yarn run i18n:extract

- name: Crowdin push & pull translations
- name: Crowdin push translations
uses: crowdin/github-action@v1
id: crowdin-download
with:
upload_sources: true
upload_translations: false
download_translations: false
push_sources: true
source: translations/en.po
translation: translations/%two_letters_code%.po
project_id: ${{ secrets.CROWDIN_PROJECT_ID }}
token: ${{ secrets.CROWDIN_PERSONAL_TOKEN }}

- name: Crowdin pre-translation
run: node ./scripts/crowdin/pretranslate.mjs

- name: Crowdin pull translations
uses: crowdin/github-action@v1
id: crowdin-download
with:
upload_sources: false
upload_translations: false
download_translations: true
source: translations/en.po
translation: translations/%two_letters_code%.po
project_id: ${{ secrets.CROWDIN_PROJECT_ID }}
token: ${{ secrets.CROWDIN_PERSONAL_TOKEN }}
commit_message: 'chore(translation): update translations [skip ci]'

localization_branch_name: ${{inputs.localization_branch_name || env.LOCALIZATION_BRANCH_NAME}}
create_pull_request: ${{inputs.create_pull_request}}
localization_branch_name: 'l10n_crowdin_translations'
create_pull_request: true
pull_request_title: '🤖chore(translation): update translations'
pull_request_body: 'New Crowdin pull request with translations'
pull_request_base_branch_name: 'next'
Expand Down
13 changes: 0 additions & 13 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,8 @@ on:
- 'next'

jobs:
localization:
if: ${{ github.ref == 'refs/heads/next' }}
uses: ./.github/workflows/crowdin.yml
secrets:
CROWDIN_PROJECT_ID: ${{ secrets.CROWDIN_PROJECT_ID }}
CROWDIN_PERSONAL_TOKEN: ${{ secrets.CROWDIN_PERSONAL_TOKEN }}
PAT: ${{ secrets.PAT }}
with:
create_pull_request: true

publish:
if: ${{ always() }}
runs-on: ubuntu-latest
needs:
- localization
steps:
- uses: actions/checkout@v4
with:
Expand Down
2 changes: 0 additions & 2 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@ jobs:
CROWDIN_PROJECT_ID: ${{ secrets.CROWDIN_PROJECT_ID }}
CROWDIN_PERSONAL_TOKEN: ${{ secrets.CROWDIN_PERSONAL_TOKEN }}
PAT: ${{ secrets.PAT }}
with:
create_pull_request: true

release:
runs-on: ubuntu-latest
Expand Down
159 changes: 159 additions & 0 deletions scripts/crowdin/pretranslate.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
const projectId = process.env.CROWDIN_PROJECT_ID;
const token = process.env.CROWDIN_PERSONAL_TOKEN;

const BASE_URL = `https://api.crowdin.com/api/v2/projects/${projectId}`;
const preTranslateURL = `${BASE_URL}/pre-translations`;
const REQUEST_INTERVAL_TIMEOUT = 10_000;
const MAXIMUM_REQUEST_RETRIES = 12;

const requestData = {
method: 'mt',
engineId: 410374,
autoApproveOption: 'all',
duplicateTranslations: false,
skipApprovedTranslations: true,
translateUntranslatedOnly: true,
translateWithPerfectMatchOnly: false,
};

const getMachineTranslationEngineID = async () =>{
try {
const response = await fetch('https://api.crowdin.com/api/v2/mts', {
headers: {
Authorization: `Bearer ${token}`,
},
});

if (!response.ok) {
throw new Error(`Failed to get target language ids`);
}

const responseData = await response.json();
const engineId = responseData.data[0].data.id ;

return engineId;

} catch (error) {
console.error('Error:', error);
throw error;
}
}

const getLanguageIds = async () => {
try {
const response = await fetch(`${BASE_URL}`, {
headers: {
Authorization: `Bearer ${token}`,
},
});

if (!response.ok) {
throw new Error(`Failed to get target language ids`);
}

const responseData = await response.json();
const languageIds = responseData.data.targetLanguageIds;

return languageIds;
} catch (error) {
console.error('Error:', error);
throw error;
}
};

const getSourceFileId = async () => {
try {
const response = await fetch(`${BASE_URL}/files`, {
headers: {
Authorization: `Bearer ${token}`,
},
});

if (!response.ok) {
throw new Error(`Failed to get source file id`);
}

const responseData = await response.json();
const sourceFileId = responseData.data[0].data.id;

return sourceFileId;
} catch (error) {
console.error('Error:', error);
throw error;
}
};

const sendPreTranslateRequest = async ({ sourceFileId, languageIds }) => {
try {
const response = await fetch(preTranslateURL, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${token}`,
},
body: JSON.stringify({ ...requestData, fileIds: [sourceFileId], languageIds }),
});

if (!response.ok) {
throw new Error(`Failed to initiate pre-translation. Status: ${response.status}`);
}

const responseData = await response.json();
const preTranslationId = responseData.data.identifier;

return preTranslationId;
} catch (error) {
console.error('Error:', error);
throw error;
}
};

const checkPreTranslateStatus = async (preTranslationId) => {
const maxAttempts = MAXIMUM_REQUEST_RETRIES;
let attempt = 0;

const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));

while (attempt < maxAttempts) {
try {
const response = await fetch(`${preTranslateURL}/${preTranslationId}`, {
headers: {
Authorization: `Bearer ${token}`,
},
});

if (!response.ok) {
throw new Error(`Failed to get pre-translation status. Status: ${response.status}`);
}

const responseData = await response.json();

const status = responseData.data.status;

if (status === 'finished') {
console.log('Pre-translation finished!');
process.exit(0);
} else {
console.log(`Pre-translation status: ${status}. Retrying in 10 seconds...`);
await delay(REQUEST_INTERVAL_TIMEOUT);
attempt++;
}
} catch (error) {
console.error('Error:', error);
throw error;
}
}

throw new Error('Timeout: Pre-translation did not succeed within the specified time.');
};

(async () => {
try {
const [sourceFileId, languageIds] = await Promise.all([getSourceFileId(), getLanguageIds()]);
const preTranslationId = await sendPreTranslateRequest({ sourceFileId, languageIds });
await checkPreTranslateStatus(preTranslationId);
} catch (error) {
console.error('Error:', error);
process.exit(1);
}
})();

0 comments on commit be4b290

Please sign in to comment.