-
-
Notifications
You must be signed in to change notification settings - Fork 343
Automate language names in en.json with Weblate API, native names, and regional disambiguation #1188
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Draft
Copilot
wants to merge
7
commits into
main
Choose a base branch
from
copilot/automate-language-name-adding
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+461
−35
Draft
Automate language names in en.json with Weblate API, native names, and regional disambiguation #1188
Changes from 2 commits
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
0be54da
Initial plan
Copilot 153ecd1
feat: Add automated workflow to update language names in en.json
Copilot f3e817e
fix: Address feedback - add Weblate API, native names, validation, an…
Copilot b735ad1
chore: Remove pycache and update gitignore
Copilot 6926aab
Remove redundant imports
katosdev 6f77eae
fix: Add region qualifiers to Portuguese and Chinese variants for cla…
Copilot 9bc6b45
Fix duplicated language names
katosdev File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,180 @@ | ||
| #!/usr/bin/env python3 | ||
| """ | ||
| Script to automatically update language names in the English translation file. | ||
| Scans for locale files and ensures all languages are present in en.json. | ||
| """ | ||
| import json | ||
| import logging | ||
| import sys | ||
| from pathlib import Path | ||
| from typing import Dict, List | ||
|
|
||
| from babel import Locale, UnknownLocaleError | ||
|
|
||
| LOCALES_DIR = Path('frontend/locales') | ||
| EN_JSON_PATH = LOCALES_DIR / 'en.json' | ||
|
|
||
| # Mapping for special/custom locale codes that don't follow standard BCP 47 | ||
| CUSTOM_LOCALE_MAPPINGS = { | ||
| 'ar-AA': ('ar', 'Arabic'), # Generic Arabic | ||
| 'en': ('en', 'English'), | ||
| } | ||
|
|
||
|
|
||
| def setup_logging(): | ||
| logging.basicConfig( | ||
| level=logging.INFO, | ||
| format='%(asctime)s %(levelname)s: %(message)s' | ||
| ) | ||
|
|
||
|
|
||
| def get_locale_files() -> List[str]: | ||
| """Get all locale codes from JSON files in the locales directory.""" | ||
| if not LOCALES_DIR.exists(): | ||
| logging.error("Locales directory not found: %s", LOCALES_DIR) | ||
| return [] | ||
|
|
||
| locale_codes = [] | ||
| for file in sorted(LOCALES_DIR.glob('*.json')): | ||
| # Extract locale code from filename (e.g., "en.json" -> "en") | ||
| locale_code = file.stem | ||
| locale_codes.append(locale_code) | ||
|
|
||
| logging.info("Found %d locale files", len(locale_codes)) | ||
| return sorted(locale_codes) | ||
|
|
||
|
|
||
| def get_language_name(locale_code: str) -> str: | ||
| """ | ||
| Get the English display name for a locale code. | ||
|
|
||
| Args: | ||
| locale_code: Language/locale code (e.g., 'en', 'pt-BR', 'zh-CN') | ||
|
|
||
| Returns: | ||
| English display name for the language | ||
| """ | ||
| # Check custom mappings first | ||
| if locale_code in CUSTOM_LOCALE_MAPPINGS: | ||
| _, name = CUSTOM_LOCALE_MAPPINGS[locale_code] | ||
| return name | ||
|
|
||
| try: | ||
| # Parse locale code using Babel | ||
| locale = Locale.parse(locale_code.replace('-', '_')) | ||
|
|
||
| # Get English display name | ||
| display_name = locale.get_display_name('en') | ||
|
|
||
| if not display_name: | ||
| # Fallback to language name if full display name not available | ||
| display_name = locale.english_name | ||
|
|
||
| return display_name | ||
|
|
||
| except (UnknownLocaleError, ValueError) as e: | ||
| logging.warning("Could not parse locale '%s': %s", locale_code, e) | ||
| # Fallback: capitalize the locale code | ||
| return locale_code.replace('-', ' ').replace('_', ' ').title() | ||
|
|
||
|
|
||
| def load_en_json() -> dict: | ||
| """Load the English translation JSON file.""" | ||
| if not EN_JSON_PATH.exists(): | ||
| logging.error("English translation file not found: %s", EN_JSON_PATH) | ||
| return {} | ||
|
|
||
| try: | ||
| with EN_JSON_PATH.open('r', encoding='utf-8') as f: | ||
| return json.load(f) | ||
| except (IOError, json.JSONDecodeError) as e: | ||
| logging.error("Failed to load %s: %s", EN_JSON_PATH, e) | ||
| return {} | ||
|
|
||
|
|
||
| def save_en_json(data: dict): | ||
| """Save the English translation JSON file.""" | ||
| try: | ||
| with EN_JSON_PATH.open('w', encoding='utf-8') as f: | ||
| # Use 4-space indentation to match existing file format | ||
| json.dump(data, f, ensure_ascii=False, indent=4) | ||
| # Add newline at end of file | ||
| f.write('\n') | ||
| logging.info("Saved updated en.json") | ||
| except IOError as e: | ||
| logging.error("Failed to save %s: %s", EN_JSON_PATH, e) | ||
| sys.exit(1) | ||
|
|
||
|
|
||
| def update_language_names(en_data: dict, locale_codes: List[str]) -> bool: | ||
| """ | ||
| Update the languages section in en.json with all locale codes. | ||
|
|
||
| Args: | ||
| en_data: The parsed en.json data | ||
| locale_codes: List of all locale codes from files | ||
|
|
||
| Returns: | ||
| True if changes were made, False otherwise | ||
| """ | ||
| # Ensure languages section exists | ||
| if 'languages' not in en_data: | ||
| en_data['languages'] = {} | ||
| logging.info("Created 'languages' section in en.json") | ||
|
|
||
| languages = en_data['languages'] | ||
| original_languages = languages.copy() | ||
|
|
||
| # Add any missing languages | ||
| added_count = 0 | ||
| for locale_code in locale_codes: | ||
| if locale_code not in languages: | ||
| language_name = get_language_name(locale_code) | ||
| languages[locale_code] = language_name | ||
| logging.info("Added language: %s = %s", locale_code, language_name) | ||
| added_count += 1 | ||
|
|
||
| # Sort languages alphabetically by key | ||
| en_data['languages'] = dict(sorted(languages.items())) | ||
|
|
||
| # Check if anything changed | ||
| changed = (original_languages != en_data['languages']) | ||
|
|
||
| if changed: | ||
| logging.info("Updated %d language names", added_count) | ||
| else: | ||
| logging.info("All languages already present, no changes needed") | ||
|
|
||
| return changed | ||
|
|
||
|
|
||
| def main(): | ||
| setup_logging() | ||
| logging.info("🔄 Starting language names update") | ||
|
|
||
| # Get all locale files | ||
| locale_codes = get_locale_files() | ||
| if not locale_codes: | ||
| logging.error("No locale files found") | ||
| sys.exit(1) | ||
|
|
||
| # Load English translation file | ||
| en_data = load_en_json() | ||
| if not en_data: | ||
| logging.error("Failed to load English translation file") | ||
| sys.exit(1) | ||
|
|
||
| # Update language names | ||
| changed = update_language_names(en_data, locale_codes) | ||
|
|
||
| if changed: | ||
| save_en_json(en_data) | ||
| logging.info("✅ Language names updated successfully") | ||
| else: | ||
| logging.info("✅ No updates needed, en.json is already up-to-date") | ||
|
|
||
| sys.exit(0) | ||
|
|
||
|
|
||
| if __name__ == "__main__": | ||
| main() | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,70 @@ | ||
| name: Update Language Names | ||
|
|
||
| on: | ||
| push: | ||
| branches: [ main ] | ||
| paths: | ||
| - 'frontend/locales/*.json' | ||
| - '.github/scripts/update_language_names.py' | ||
| - '.github/workflows/update-language-names.yml' | ||
| workflow_dispatch: | ||
|
|
||
| permissions: | ||
| contents: write | ||
| pull-requests: write | ||
|
|
||
| jobs: | ||
| update-language-names: | ||
| runs-on: ubuntu-latest | ||
|
|
||
| steps: | ||
| - name: Checkout code | ||
| uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 | ||
| with: | ||
| fetch-depth: 0 | ||
|
|
||
| - name: Set up Python | ||
| uses: actions/setup-python@83679a892e2d95755f2dac6acb0bfd1e9ac5d548 | ||
| with: | ||
| python-version: '3.8' | ||
| cache: 'pip' | ||
| cache-dependency-path: .github/workflows/update-languages/requirements.txt | ||
|
|
||
| - name: Install dependencies | ||
| run: | | ||
| python -m pip install --upgrade pip | ||
| pip install -r .github/workflows/update-languages/requirements.txt | ||
|
|
||
| - name: Run language names update script | ||
| run: python .github/scripts/update_language_names.py | ||
|
|
||
| - name: Check for en.json changes | ||
| run: | | ||
| if git diff --quiet -- frontend/locales/en.json; then | ||
| echo "changed=false" >> $GITHUB_ENV | ||
| else | ||
| echo "changed=true" >> $GITHUB_ENV | ||
| fi | ||
|
|
||
| - name: Create Pull Request | ||
| if: env.changed == 'true' | ||
| uses: peter-evans/create-pull-request@98357b18bf14b5342f975ff684046ec3b2a07725 | ||
| with: | ||
| token: ${{ secrets.GITHUB_TOKEN }} | ||
| branch: automation/update-language-file | ||
| base: main | ||
| title: "Update language names in en.json" | ||
| commit-message: "chore: update language names in en.json" | ||
| body: | | ||
| This PR automatically updates the language names in `frontend/locales/en.json` based on the available locale files. | ||
|
|
||
| New languages have been added to ensure all locale files have corresponding language names in the English translation file. | ||
|
|
||
| 🤖 This PR was automatically created by the update-language-names workflow. | ||
| path: . | ||
| add-paths: | | ||
| frontend/locales/en.json | ||
|
|
||
| - name: No updates needed | ||
| if: env.changed == 'false' | ||
| run: echo "✅ en.json language names are already up-to-date" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| babel |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.