diff --git a/.github/workflows/check_for_crowdin_updates.yml b/.github/workflows/check_for_crowdin_updates.yml index 8c975fd..25a8877 100644 --- a/.github/workflows/check_for_crowdin_updates.yml +++ b/.github/workflows/check_for_crowdin_updates.yml @@ -19,7 +19,8 @@ jobs: with: repository: 'oxen-io/session-android' path: 'android' - ref: 'dev' + submodules: recursive + ref: 'release/1.20.0' - name: Checkout Desktop uses: actions/checkout@v4 with: @@ -37,6 +38,16 @@ jobs: with: python-version: 3.8 cache: 'pip' # caching pip dependencies + - name: Setup Java + uses: actions/setup-java@v4 + with: + distribution: 'temurin' + java-version: 17 + cache: gradle + + - name: Setup Gradle + uses: gradle/actions/setup-gradle@v4 + - name: Install Dependencies run: | pip install -r ${{ github.workspace }}/scripts/crowdin/requirements.txt @@ -51,12 +62,29 @@ jobs: --glossary_id 407522 \ --concept_id 36 \ --skip-untranslated-strings + + - name: Upload xliff artefacts + uses: actions/upload-artifact@v4 + with: + name: session-xliff-artefact + path: "{{ github.workspace }}/raw_translations/*" + overwrite: true + if-no-files-found: warn + retention-days: 7 + - name: Prepare Android Strings run: | python "${{ github.workspace }}/scripts/crowdin/generate_android_strings.py" \ "${{ github.workspace }}/raw_translations" \ - "${{ github.workspace }}/android/app/src/main/res" \ - "${{ github.workspace }}/android/session-android/libsession/src/main/java/org/session/libsession/utilities/NonTranslatableStringConstants.kt" + "${{ github.workspace }}/android/libsession/src/main/res" \ + "${{ github.workspace }}/android/libsession/src/main/java/org/session/libsession/utilities/NonTranslatableStringConstants.kt" + + + + - name: Print Android Strings + run: | + ls -l "${{ github.workspace }}/android/libsession/src/main/res/" + - name: Prepare Desktop Strings run: | rm -rf ${{ github.workspace }}/desktop/_locales/* @@ -76,8 +104,8 @@ jobs: with: name: session-android-artefact path: | - ${{ github.workspace }}/android/app/src/main/res/values*/strings.xml - ${{ github.workspace }}/android/session-android/libsession/src/main/java/org/session/libsession/utilities/NonTranslatableStringConstants.kt + ${{ github.workspace }}/android/libsession/src/main/res/values*/strings.xml + ${{ github.workspace }}/android/libsession/src/main/java/org/session/libsession/utilities/NonTranslatableStringConstants.kt overwrite: true if-no-files-found: warn retention-days: 7 @@ -101,6 +129,10 @@ jobs: overwrite: true if-no-files-found: warn retention-days: 7 + + - name: Validate strings for Android + run: ${{ github.workspace }}/android/gradlew :libsession:packageDebugResources + # It's easier to find what went wrong with some strings if we can get the files from the artefact upload step above. # The job will still be marked as failed and no Pull Requests will be made. - name: Prepare QA strings @@ -121,6 +153,8 @@ jobs: + + # Not sure why yet, but uploading artefacts after creating the pull requests # seems to only include a part of what should be in. # As a dirty fix we upload the artefacts first, and then make the pull request diff --git a/crowdin/download_translations_from_crowdin.py b/crowdin/download_translations_from_crowdin.py index 6a7e2f3..01b4285 100644 --- a/crowdin/download_translations_from_crowdin.py +++ b/crowdin/download_translations_from_crowdin.py @@ -3,6 +3,7 @@ import json import time import sys +import re import argparse from colorama import Fore, Style, init @@ -48,11 +49,31 @@ def download_file(url, output_path): for chunk in response.iter_content(chunk_size=8192): f.write(chunk) + sanitize_downloaded_file(output_path) + + +# Sanitize crowdin translations and common user mistakes +def sanitize_downloaded_file(file_path): + with open(file_path, 'r', encoding='utf-8') as file: + xml_content = file.read() + + correct = '<br/>' + # the only correct br tag is . + # This replaces <.{0,2}br.{0,2}> + # as we sometimes have a \ or a / or both misplaces + updated_content = re.sub("<.{0,2}br.{0,2}>",correct,xml_content) + + + # Write the updated content back to the file + with open(file_path, 'w', encoding='utf-8') as file: + file.write(updated_content) + + # Main function to handle the logic def main(): # Retrieve the list of languages print(f"{Fore.WHITE}⏳ Retrieving project details...{Style.RESET_ALL}", end='\r') - project_response = requests.get(f"{CROWDIN_API_BASE_URL}/projects/{CROWDIN_PROJECT_ID}", + project_response = requests.get(f"{CROWDIN_API_BASE_URL}/projects/{CROWDIN_PROJECT_ID}", headers={"Authorization": f"Bearer {CROWDIN_API_TOKEN}"}) check_error(project_response) project_details = project_response.json()['data'] @@ -113,7 +134,7 @@ def main(): lang_id = language['id'] lang_locale = language['locale'] prefix = f"({index:02d}/{num_languages:02d})" - + # Request export of translations for the specific language print(f"\033[2K{Fore.WHITE}⏳ {prefix} Exporting translations for {lang_locale}...{Style.RESET_ALL}", end='\r') export_payload = { @@ -148,7 +169,7 @@ def main(): # Download non-translatable terms (if requested) if CROWDIN_GLOSSARY_ID is not None and CROWDIN_CONCEPT_ID is not None: print(f"{Fore.WHITE}⏳ Retrieving non-translatable strings...{Style.RESET_ALL}", end='\r') - static_string_response = requests.get(f"{CROWDIN_API_BASE_URL}/glossaries/{CROWDIN_GLOSSARY_ID}/terms?conceptId={CROWDIN_CONCEPT_ID}&limit=500", + static_string_response = requests.get(f"{CROWDIN_API_BASE_URL}/glossaries/{CROWDIN_GLOSSARY_ID}/terms?conceptId={CROWDIN_CONCEPT_ID}&limit=500", headers={"Authorization": f"Bearer {CROWDIN_API_TOKEN}"}) check_error(static_string_response) diff --git a/crowdin/generate_android_strings.py b/crowdin/generate_android_strings.py index 1355148..ee8d532 100644 --- a/crowdin/generate_android_strings.py +++ b/crowdin/generate_android_strings.py @@ -67,7 +67,7 @@ def repl(match): def clean_string(text): # We can use standard XML escaped characters for most things (since XLIFF is an XML format) but - # want the following cases escaped in a particulat way + # want the following cases escaped in a particular way text = text.replace("'", r"\'") text = text.replace(""", "\"") text = text.replace("\"", "\\\"")