diff --git a/.github/actions/translation-tracker/index.js b/.github/actions/translation-tracker/index.js
new file mode 100644
index 0000000000..fe1ba04807
--- /dev/null
+++ b/.github/actions/translation-tracker/index.js
@@ -0,0 +1,239 @@
+const { execSync } = require('child_process');
+const fs = require('fs');
+const path = require('path');
+
+const SUPPORTED_LANGUAGES = ['es', 'hi', 'ko', 'zh-Hans'];
+
+
+function getChangedFiles(testFiles = null) {
+ // Allow passing test files for local development
+ if (testFiles) {
+ console.log('๐งช Using provided test files for local testing');
+ return testFiles.filter(file =>
+ file.startsWith('src/content/examples/en') && file.endsWith('.mdx')
+ );
+ }
+
+ try {
+ const gitCommand = process.env.GITHUB_EVENT_NAME === 'pull_request'
+ ? 'git diff --name-only HEAD~1 HEAD'
+ : 'git diff --name-only HEAD~1 HEAD';
+
+ const changedFilesOutput = execSync(gitCommand, { encoding: 'utf8' });
+ const allChangedFiles = changedFilesOutput.trim().split('\n').filter(file => file.length > 0);
+
+ const changedExampleFiles = allChangedFiles.filter(file =>
+ file.startsWith('src/content/examples/en') && file.endsWith('.mdx')
+ );
+
+ console.log(`๐ Total changed files: ${allChangedFiles.length}`);
+ console.log(`๐ Changed English example files: ${changedExampleFiles.length}`);
+
+ if (changedExampleFiles.length > 0) {
+ console.log('๐ Changed English example files:');
+ changedExampleFiles.forEach(file => console.log(` - ${file}`));
+ }
+
+ return changedExampleFiles;
+ } catch (error) {
+ console.error('โ Error getting changed files:', error.message);
+ return [];
+ }
+}
+
+/**
+ * Check if a file exists
+ */
+function fileExists(filePath) {
+ try {
+ return fs.existsSync(filePath);
+ } catch (error) {
+ return false;
+ }
+}
+
+
+function getFileModTime(filePath) {
+ try {
+ return fs.statSync(filePath).mtime;
+ } catch (error) {
+ return null;
+ }
+}
+
+
+function checkTranslationStatus(changedExampleFiles) {
+ const translationStatus = {
+ needsUpdate: [],
+ missing: [],
+ upToDate: []
+ };
+
+ changedExampleFiles.forEach(englishFile => {
+ console.log(`\n๐ Checking translations for: ${englishFile}`);
+
+ const englishModTime = getFileModTime(englishFile);
+ if (!englishModTime) {
+ console.log(`โ ๏ธ Could not get modification time for English file`);
+ return;
+ }
+
+ SUPPORTED_LANGUAGES.forEach(language => {
+ const translationPath = englishFile.replace('/en/', `/${language}/`);
+ const exists = fileExists(translationPath);
+
+ if (!exists) {
+ console.log(` โ ${language}: Missing translation`);
+ translationStatus.missing.push({
+ englishFile,
+ language,
+ translationPath,
+ status: 'missing'
+ });
+ } else {
+ const translationModTime = getFileModTime(translationPath);
+ const isOutdated = translationModTime < englishModTime;
+
+ if (isOutdated) {
+ console.log(` ๐ ${language}: Needs update (English: ${englishModTime.toISOString()}, Translation: ${translationModTime.toISOString()})`);
+ translationStatus.needsUpdate.push({
+ englishFile,
+ language,
+ translationPath,
+ status: 'outdated',
+ englishModTime,
+ translationModTime
+ });
+ } else {
+ console.log(` โ
${language}: Up to date`);
+ translationStatus.upToDate.push({
+ englishFile,
+ language,
+ translationPath,
+ status: 'up-to-date'
+ });
+ }
+ }
+ });
+ });
+
+ return translationStatus;
+}
+
+
+function displaySummary(translationStatus) {
+ console.log('\n๐ TRANSLATION STATUS SUMMARY');
+ console.log('โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ');
+
+ console.log(`๐ Missing translations: ${translationStatus.missing.length}`);
+ if (translationStatus.missing.length > 0) {
+ translationStatus.missing.forEach(item => {
+ console.log(` - ${item.language}: ${item.englishFile}`);
+ });
+ }
+
+ console.log(`๐ Outdated translations: ${translationStatus.needsUpdate.length}`);
+ if (translationStatus.needsUpdate.length > 0) {
+ translationStatus.needsUpdate.forEach(item => {
+ console.log(` - ${item.language}: ${item.englishFile}`);
+ });
+ }
+
+ console.log(`โ
Up-to-date translations: ${translationStatus.upToDate.length}`);
+
+
+}
+
+/**
+ * Explore repository structure (focusing on examples as requested)
+ */
+function exploreRepoStructure() {
+ console.log('\n๐ REPOSITORY STRUCTURE ANALYSIS');
+ console.log('โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ');
+
+ try {
+ const examplesPath = 'src/content/examples';
+ console.log(`๐ Examples path: ${examplesPath}`);
+
+ if (fs.existsSync(examplesPath)) {
+ const languages = fs.readdirSync(examplesPath)
+ .filter(item => fs.statSync(path.join(examplesPath, item)).isDirectory())
+ .filter(item => !item.startsWith('.') && item !== 'images');
+
+ console.log(`๐ Available languages: ${languages.join(', ')}`);
+
+ // Count example files in each language
+ languages.forEach(lang => {
+ const langPath = path.join(examplesPath, lang);
+ try {
+ let totalFiles = 0;
+ const categories = fs.readdirSync(langPath)
+ .filter(item => fs.statSync(path.join(langPath, item)).isDirectory());
+
+ categories.forEach(category => {
+ const categoryPath = path.join(langPath, category);
+ const countFilesRecursively = (dir) => {
+ const items = fs.readdirSync(dir);
+ let count = 0;
+ items.forEach(item => {
+ const itemPath = path.join(dir, item);
+ if (fs.statSync(itemPath).isDirectory()) {
+ count += countFilesRecursively(itemPath);
+ } else if (item.endsWith('.mdx')) {
+ count++;
+ }
+ });
+ return count;
+ };
+ totalFiles += countFilesRecursively(categoryPath);
+ });
+
+ console.log(` ${lang}: ${totalFiles} example files across ${categories.length} categories`);
+ } catch (error) {
+ console.log(` ${lang}: Error reading directory - ${error.message}`);
+ }
+ });
+ } else {
+ console.log(`โ Examples path does not exist: ${examplesPath}`);
+ }
+ } catch (error) {
+ console.error('โ Error exploring repository structure:', error.message);
+ }
+}
+
+
+function main(testFiles = null) {
+ console.log('๐ฏ p5.js Example Translation Tracker - Week 1 Prototype');
+ console.log('โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ');
+ console.log(`๐
Event: ${process.env.GITHUB_EVENT_NAME || 'local'}`);
+ console.log(`๐ Working directory: ${process.cwd()}`);
+ console.log(`๐ Tracking languages: ${SUPPORTED_LANGUAGES.join(', ')}`);
+
+ exploreRepoStructure();
+
+ // Get changed files (supports both git and test files)
+ const changedExampleFiles = getChangedFiles(testFiles);
+
+ if (changedExampleFiles.length === 0) {
+ console.log('\nโจ No changes detected in English example files.');
+ console.log('๐ Nothing to track for translations in this commit!');
+ return;
+ }
+
+ const translationStatus = checkTranslationStatus(changedExampleFiles);
+
+ displaySummary(translationStatus);
+}
+
+// Export for testing
+module.exports = {
+ main,
+ getChangedFiles,
+ checkTranslationStatus,
+ exploreRepoStructure
+};
+
+
+if (require.main === module) {
+ main();
+}
diff --git a/.github/actions/translation-tracker/package.json b/.github/actions/translation-tracker/package.json
new file mode 100644
index 0000000000..7284cba02a
--- /dev/null
+++ b/.github/actions/translation-tracker/package.json
@@ -0,0 +1,26 @@
+{
+ "name": "p5js-translation-tracker",
+ "version": "0.1.1",
+ "description": "GitHub Action to track translation status for p5.js examples and documentation",
+ "main": "index.js",
+ "scripts": {
+ "start": "node index.js",
+ "test": "node index.js"
+ },
+ "keywords": [
+ "p5.js",
+ "translation",
+ "documentation",
+ "github-actions",
+ "automation"
+ ],
+ "author": "Divyansh Srivastava",
+ "license": "LGPL-2.1",
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "dependencies": {
+ "@actions/core": "^1.10.0",
+ "@actions/github": "^5.1.1"
+ }
+}
\ No newline at end of file
diff --git a/.github/actions/translation-tracker/test-local.js b/.github/actions/translation-tracker/test-local.js
new file mode 100755
index 0000000000..79cd71a5e0
--- /dev/null
+++ b/.github/actions/translation-tracker/test-local.js
@@ -0,0 +1,20 @@
+
+
+const { main } = require('./index.js');
+
+// Test scenarios using actual example files that exist
+const testFiles = [
+ 'src/content/examples/en/01_Shapes_And_Color/00_Shape_Primitives/description.mdx',
+ 'src/content/examples/en/02_Animation_And_Variables/00_Drawing_Lines/description.mdx',
+ 'src/content/examples/en/03_Imported_Media/00_Words/description.mdx'
+];
+
+console.log('๐งช Testing Example Translation Tracker Locally');
+console.log('===============================================\n');
+
+// Run the main function with test files
+main(testFiles);
+
+console.log('\n๐ก This demonstrates local testing capability as requested by mentor');
+console.log('๐ง The git logic is now separated and modular for easier testing');
+console.log('๐ Now tracking examples instead of tutorials as requested');
\ No newline at end of file
diff --git a/.github/workflows/translation-sync.yml b/.github/workflows/translation-sync.yml
new file mode 100644
index 0000000000..b3bbe43440
--- /dev/null
+++ b/.github/workflows/translation-sync.yml
@@ -0,0 +1,34 @@
+name: Translation Sync Tracker
+
+on:
+ push:
+ branches: [main]
+ paths:
+ - 'src/content/reference/en/**'
+ pull_request:
+ branches: [main]
+ paths:
+ - 'src/content/reference/en/**'
+
+jobs:
+ track-translation-changes:
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v4
+ with:
+ fetch-depth: 2 # Fetch previous commit to compare changes
+
+ - name: Setup Node.js
+ uses: actions/setup-node@v4
+ with:
+ node-version: '18'
+
+ - name: Install dependencies
+ run: npm ci
+
+ - name: Run translation tracker
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ run: node .github/actions/translation-tracker/index.js
\ No newline at end of file
diff --git a/src/content/examples/en/01_Shapes_And_Color/00_Shape_Primitives/description.mdx b/src/content/examples/en/01_Shapes_And_Color/00_Shape_Primitives/description.mdx
index 428f348709..6d2b99d0e7 100644
--- a/src/content/examples/en/01_Shapes_And_Color/00_Shape_Primitives/description.mdx
+++ b/src/content/examples/en/01_Shapes_And_Color/00_Shape_Primitives/description.mdx
@@ -9,7 +9,7 @@ relatedReference:
---
This program demonstrates the use of the basic shape
-primitive functions
+primitive functions (sample change for testing)
square(),
rect(),
ellipse(),