Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 49 additions & 0 deletions .github/workflows/update-translation-stats.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
name: "Update Translation Statistics"

on:
schedule:
- cron: '0 0 * * 6' # Run at midnight on Saturdays
workflow_dispatch: # Allow manual trigger
pull_request:

jobs:
update-stats:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
ref: ${{ github.event_name == 'pull_request' && github.head_ref || github.ref_name }}
fetch-depth: 0

- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.10'

- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r scripts/transifex/requirements.txt
sudo apt-get update
sudo apt-get install -y chromium-browser

- name: Run statistics update
env:
TRANSIFEX_USERNAME: ${{ secrets.TRANSIFEX_USERNAME }}
TRANSIFEX_PASSWORD: ${{ secrets.TRANSIFEX_PASSWORD }}
CI: true
run: |
cd scripts/transifex
python main.py

- name: Update README
run: python scripts/transifex/update_readme.py

- name: Commit and push changes
if: ${{ github.event_name != 'pull_request' }}
run: |
git config --local user.email "github-actions@github.com"
git config --local user.name "GitHub Action"
git add reports/ README.md
git diff --quiet && git diff --staged --quiet || git commit -m "Update translation statistics"
git push origin ${{ github.ref_name }}
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@
locales/
venv/
__pycache__/
transifex_cookies.json
17 changes: 17 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,20 @@
***

با تشکر از همراهی شما در گسترش و بهبود مستندات پایتون به زبان فارسی!


<!-- STATS_START -->
## آمار ترجمه

### مشارکت‌های این هفته کاربران

![مشارکت‌های این هفته کاربران](reports/contributors/2025-04-01.png)

(به‌روزرسانی: 2025-04-01)

### پیشرفت ترجمه

![پیشرفت ترجمه](reports/progress/2025-04-01.png)

(به‌روزرسانی: 2025-04-01)
<!-- STATS_END -->
Binary file added reports/contributors/2025-04-01.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added reports/progress/2025-04-01.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
36 changes: 36 additions & 0 deletions scripts/transifex/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import sys
import os
from transifex_browser import get_driver_with_login, save_cookies, kill_browser
from visualizer import visualize_string_counts, visualize_user_contributions


def main():
# Check for environment variables first (for CI/CD)
username = os.environ.get("TRANSIFEX_USERNAME")
password = os.environ.get("TRANSIFEX_PASSWORD")

# Fall back to command line args if env vars not found
if not username or not password:
if len(sys.argv) != 3:
print("Usage: python main.py <username> <password>")
print(
"Or set TRANSIFEX_USERNAME and TRANSIFEX_PASSWORD environment variables"
)
sys.exit(1)
username = sys.argv[1]
password = sys.argv[2]

driver = get_driver_with_login(username, password)
# Navigate to a specific URL if needed.
driver.get("https://app.transifex.com/python-doc/python-newest/translate/#fa/$")
# Allow time for the page to load.
driver.implicitly_wait(10)
# Update cookies after visiting the page.
save_cookies(driver)
kill_browser()
visualize_user_contributions()
visualize_string_counts()


if __name__ == "__main__":
main()
4 changes: 4 additions & 0 deletions scripts/transifex/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
matplotlib
requests
helium
selenium
52 changes: 52 additions & 0 deletions scripts/transifex/transifex_browser.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import json
from helium import start_chrome, click, write, kill_browser
from selenium.webdriver.common.by import By
from time import sleep

COOKIE_FILE = "transifex_cookies.json"
TRANSIFEX_URL = "https://www.transifex.com/dashboard/"


def save_cookies(driver):
cookies = driver.get_cookies()
with open(COOKIE_FILE, "w") as f:
json.dump(cookies, f)
return cookies


def is_logged_in(driver):
# Check for an element that only exists when logged in.
try:
driver.find_element(By.CSS_SELECTOR, ".user-profile")
return True
except Exception:
return False


def login_transifex(driver, username, password):
driver.get("https://app.transifex.com/signin/")
sleep(5)
try:
click("Allow all")
except:
pass
write(username, into="Email")
write(password, into="Password")
click("Log in") # Adjust selector if needed.
# Allow time for login and cookie propagation.
sleep(5)
try:
click("I agree, let's go!")
except:
pass
driver.refresh()
sleep(5)
save_cookies(driver)
return driver


def get_driver_with_login(username, password):
driver = start_chrome(headless=True)
driver.set_window_size(1920, 1080)
login_transifex(driver, username, password)
return driver
99 changes: 99 additions & 0 deletions scripts/transifex/update_readme.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import os
import re
import glob
from datetime import datetime

# Calculate the path to the repository root (2 levels up from this script)
REPO_ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), "../.."))
README_PATH = os.path.join(REPO_ROOT, "README.md")
contributors_dir = os.path.join(REPO_ROOT, "reports", "contributors")
progress_dir = os.path.join(REPO_ROOT, "reports", "progress")


def find_latest_image(directory):
"""Find the latest image file in the given directory based on filename."""
pattern = os.path.join(directory, "*.png")
files = glob.glob(pattern)
if not files:
return None
# Sort the files by name (which should sort by date if the format is consistent)
latest_file = sorted(files)[-1]
# Return the path relative to the REPO_ROOT
return os.path.relpath(latest_file, REPO_ROOT).replace("\\", "/")


def update_readme():
"""Update the README.md file with the latest report images."""
today = datetime.now().strftime("%Y-%m-%d")
latest_contributors_img = find_latest_image(contributors_dir)
latest_progress_img = find_latest_image(progress_dir)

# Check if both image files exist
if not latest_contributors_img or not latest_progress_img:
print("Warning: One or both image files not found.")
if latest_contributors_img:
print(f"Found contributors image: {latest_contributors_img}")
if latest_progress_img:
print(f"Found progress image: {latest_progress_img}")
return False

# Read the current README content
with open(README_PATH, "r", encoding="utf-8") as file:
content = file.read()

# Define the stats section
stats_section = f"""## آمار ترجمه

### مشارکت‌های این هفته کاربران

![مشارکت‌های این هفته کاربران]({latest_contributors_img})

(به‌روزرسانی: {today})

### پیشرفت ترجمه

![پیشرفت ترجمه]({latest_progress_img})

(به‌روزرسانی: {today})"""

# Check if stats section already exists with markers
if "<!-- STATS_START -->" in content and "<!-- STATS_END -->" in content:
# Replace the existing stats section between markers
pattern = r"<!-- STATS_START -->.*?<!-- STATS_END -->"
updated_content = re.sub(
pattern,
f"<!-- STATS_START -->\n{stats_section}\n<!-- STATS_END -->",
content,
flags=re.DOTALL,
)
elif "## آمار ترجمه" in content:
# If old format exists without markers, replace that section
pattern = r"## آمار ترجمه.*?(?=\n##|\Z)"
updated_content = re.sub(
pattern,
f"<!-- STATS_START -->\n{stats_section}\n<!-- STATS_END -->",
content,
flags=re.DOTALL,
)
else:
# Append the stats section to the end of the README
updated_content = (
content
+ "\n\n<!-- STATS_START -->\n"
+ stats_section
+ "\n<!-- STATS_END -->"
)

# Write the updated content back to the README
with open(README_PATH, "w", encoding="utf-8") as file:
file.write(updated_content)

print(f"README.md updated successfully with:")
print(f"- Contributors image: {latest_contributors_img}")
print(f"- Progress image: {latest_progress_img}")
print(f"- Update date: {today}")
return True


if __name__ == "__main__":
update_readme()
Loading