diff --git a/.github/workflows/translate-strings.yml b/.github/workflows/translate-strings.yml index 08197f9..04c76f1 100644 --- a/.github/workflows/translate-strings.yml +++ b/.github/workflows/translate-strings.yml @@ -1,7 +1,18 @@ -name: Translate general strings +name: Translate strings on: workflow_dispatch: + inputs: + platform: + description: 'Platform to translate strings for' + required: true + default: 'all' + type: choice + options: + - all + - android + - common + - ios permissions: contents: write @@ -18,36 +29,65 @@ jobs: with: fetch-depth: 0 - - name: Translate shared/presentation/src/commonMain/composeResources/values/strings.xml to supported languages + - name: Translate common strings to supported languages + if: ${{ github.event.inputs.platform == 'common' || github.event.inputs.platform == 'all' }} run: | python translator.py \ --api_key $API_KEY \ --output_languages $OUTPUT_LANGUAGES \ - --input_folder $INPUT_FOLDER + --input_folder $INPUT_FOLDER \ + --platform $PLATFORM env: API_KEY: ${{ secrets.DEEPL_API_KEY }} OUTPUT_LANGUAGES: "ES,FR,DE,ZH,UK,JA,RU,AR,PT,IT,KO,NL,SV,PL,TR,DA,FI,EL,HU" INPUT_FOLDER: "./shared/presentation/src/commonMain/composeResources/values" + PLATFORM: "common" - - name: Translate shared/presentation/src/androidMain/res/values/strings.xml to supported languages + - name: Translate android strings to supported languages + if: ${{ github.event.inputs.platform == 'android' || github.event.inputs.platform == 'all' }} run: | python translator.py \ --api_key $API_KEY \ --output_languages $OUTPUT_LANGUAGES \ --input_folder $INPUT_FOLDER + --platform $PLATFORM env: API_KEY: ${{ secrets.DEEPL_API_KEY }} OUTPUT_LANGUAGES: "ES,FR,DE,ZH,UK,JA,RU,AR,PT,IT,KO,NL,SV,PL,TR,DA,FI,EL,HU" INPUT_FOLDER: "./shared/presentation/src/androidMain/res/values" + PLATFORM: "android" + + - name: Translate iOS strings to supported languages + if: ${{ github.event.inputs.platform == 'ios' || github.event.inputs.platform == 'all' }} + run: | + python translator.py \ + --api_key $API_KEY \ + --output_languages $OUTPUT_LANGUAGES \ + --input_folder $INPUT_FOLDER + --platform $PLATFORM + env: + API_KEY: ${{ secrets.DEEPL_API_KEY }} + OUTPUT_LANGUAGES: "ES,FR,DE,ZH,UK,JA,RU,AR,PT,IT,KO,NL,SV,PL,TR,DA,FI,EL,HU" + INPUT_FOLDER: "./iosApp" + PLATFORM: "ios" + + - name: Add common strings to Git + if: ${{ github.event.inputs.platform == 'common' || github.event.inputs.platform == 'all' }} + run: git add shared/presentation/src/commonMain/composeResources/values* - - name: Add common strings.xml to Git + - name: Add android strings to Git + if: ${{ github.event.inputs.platform == 'android' || github.event.inputs.platform == 'all' }} run: git add shared/presentation/src/androidMain/res/values* + - name: Add ios strings to Git + if: ${{ github.event.inputs.platform == 'ios' || github.event.inputs.platform == 'all' }} + run: git add iosApp/Localizable.xcstrings + - name: Commit files run: | git config --local user.email ${{ vars.COMMITER_EMAIL }} git config --local user.name ${{ vars.COMMITER_NAME }} - git commit -a -m "Github Action automatic translation of android specific strings" + git commit -a -m "Github Action automatic translation of strings" - name: GitHub Push uses: ad-m/github-push-action@v0.8.0 diff --git a/translator.py b/translator.py index c281f3f..2aeacc9 100644 --- a/translator.py +++ b/translator.py @@ -1,6 +1,7 @@ import argparse import os import requests +import json import xml.etree.ElementTree as ElementTree # MIT License @@ -26,19 +27,21 @@ # SOFTWARE. # PERSONAL ADAPTATION BY jmanrique -# run as "python translator.py", args: api_key, input_language, output_languages, input_folder +# run as "python translator.py", args: api_key, input_language, output_languages, input_folder, platform API_KEY = "" OUTPUT_LANGUAGES = "" INPUT_FILE = "" VALUES_FOLDER = "" INPUT_LANGUAGE = "EN" +PLATFORM = "" parser = argparse.ArgumentParser(description='Translate script') parser.add_argument('--api_key', type=str, help='API Key for translation') parser.add_argument('--input_language', type=str, help='Language of the input file') parser.add_argument('--output_languages', type=str, help='ISO codes for output languages') parser.add_argument('--input_folder', type=str, help='Folder path of the file you want translate') +parser.add_argument('--platform', type=str, help='Target phone operative system, might be android, ios or common') args = parser.parse_args() if args.api_key: @@ -50,9 +53,14 @@ if args.output_languages: OUTPUT_LANGUAGES = args.output_languages +PLATFORM = args.platform + if args.input_folder: VALUES_FOLDER = args.input_folder - INPUT_FILE = VALUES_FOLDER + '/strings.xml' + if PLATFORM == 'ios': + INPUT_FILE = VALUES_FOLDER + '/Localizable.xcstrings' + else: + INPUT_FILE = VALUES_FOLDER + '/strings.xml' def create_directory_if_not_exists(directory_name): @@ -60,20 +68,88 @@ def create_directory_if_not_exists(directory_name): os.makedirs(directory_name) -def create_directories(dir_language): +def create_android_directories(dir_language): file_directory = VALUES_FOLDER + "-" + dir_language.lower() create_directory_if_not_exists(file_directory) return file_directory + languages_from_translate = INPUT_LANGUAGE languages_to_translate = OUTPUT_LANGUAGES.split(",") languages_supporting_formality = ["DE", "FR", "IT", "ES", "NL", "PL", "PT-BR", "PT-PT", "JA", "RU"] -for language_name in languages_to_translate: - language_to_translate = language_name.strip() - translated_file_directory = create_directories(language_to_translate) +def translate_ios_strings(): + # Load the existing JSON from Localizable.xcstrings + with open(INPUT_FILE, 'r', encoding='utf-8') as f: + localization_data = json.load(f) + + # Iterate through each target language and add translations + for language_name in languages_to_translate: + language_to_translate = language_name.strip().lower() + + print(f" -> Translating to {language_to_translate} =========================") + + # Iterate through all strings in the JSON structure + for key, value in localization_data['strings'].items(): + if 'en' in value['localizations']: + # Get the English value to translate + english_value = value['localizations']['en']['stringUnit']['value'] + context = value.get('comment', None) + + # Set up parameters for DeepL API + params = { + 'auth_key': API_KEY, + 'text': english_value, + 'source_lang': languages_from_translate, + "target_lang": language_to_translate.upper() + } + + if context is not None: + params['context'] = context # Optional: Provide context if needed + + if language_to_translate.upper() in languages_supporting_formality: + params["formality"] = "less" # Optional: Set informal tone for supported languages + + # Send translation request to DeepL API + try: + request = requests.post("https://api.deepl.com/v2/translate", data=params) + request.raise_for_status() # Raise an error for bad responses + result = request.json() + + # Extract the translated text + translated_text = result["translations"][0]["text"].strip() + + # Add the translation to the localization data + if 'localizations' not in value: + value['localizations'] = {} + value['localizations'][language_to_translate] = { + "stringUnit": { + "state": "translated", + "value": translated_text + } + } + + # Debug print + print(f'{english_value} --> {translated_text}') + + except requests.exceptions.RequestException as e: + print(f"Error during translation for key '{key}': {e}") + + # Write the updated JSON to Localizable.xcstrings + translated_file_path = os.path.join(VALUES_FOLDER, 'Localizable.xcstrings') + with open(translated_file_path, 'w', encoding='utf-8') as f: + json.dump(localization_data, f, ensure_ascii=False, indent=2) + + print(f"Translations written to: {translated_file_path}") + + +def translate_android_or_common_strings(): + for language_name in languages_to_translate: + language_to_translate = language_name.strip() + + translated_file_directory = create_android_directories(language_to_translate) print(" -> " + language_to_translate + " =========================") tree = ElementTree.parse(INPUT_FILE) @@ -103,3 +179,9 @@ def create_directories(dir_language): translated_file = translated_file_directory + "/strings.xml" tree.write(translated_file, encoding='utf-8') + + +if PLATFORM != 'ios': + translate_android_or_common_strings() +else: + translate_ios_strings()