database translation plugin

Post Reply
Weebey
Posts: 10
Joined: Sun Apr 21, 2024 6:22 am

database translation plugin

Post by Weebey »

Hi all,

I'm no expert coder, so with some help from AI, I coded a small plugin that enables me to translate my pages and save the translation into a new database_EN.js.

It's not actually a plugin since I didn't manage to integrate it into the admin panel, it would make my site bug out so I created a standalone php file.
My "plugin" displays a dropdown menu to select the page or subpage to translate, with text boxes for the default language of the site, and text boxes with the translation next to that.

I could really use help to integrate this into the admin panel, since I'd like to share this plugin once it's complete and functional for other people to use...

Code: Select all

<?php
// Define the path to the root directory
$rootPath = $_SERVER['DOCUMENT_ROOT'];
$filePath = $rootPath . '/data/database.js';
$enFilePath = $rootPath . '/plugins/plugin-translation/database_EN.js';

// Function to handle errors and display messages
function handleError($message) {
	echo '<p class="wcc-error">' . htmlspecialchars($message) . '</p>';
	exit;
}

// Function to get nested array value
function getNestedArrayValue($array, $keys) {
	echo "<p>Getting value for keys: " . htmlspecialchars(implode(' -> ', $keys)) . "</p>";
	foreach ($keys as $key) {
		if (!isset($array[$key])) {
			echo "<p class='wcc-error'>Key '$key' not found.</p>";
			return null;
		}
		$array = $array[$key];
	}
	return $array;
}

// Function to set nested array value
function setNestedArrayValue(&$array, $keys, $value) {
	//echo "<p>Setting value for keys: " . htmlspecialchars(implode(' -> ', $keys)) . " to '" . htmlspecialchars($value) . "'</p>";
	$current = &$array;
	foreach ($keys as $key) {
		if (!isset($current[$key])) {
			$current[$key] = [];
		}
		$current = &$current[$key];
	}
	$current = $value;
}

// Check if the main database file exists
if (!file_exists($filePath)) {
	handleError('Main database file does not exist: ' . htmlspecialchars($filePath));
}

// Read the database.js file
$content = @file_get_contents($filePath);
if ($content === false) {
	handleError('Failed to read the main database file: ' . htmlspecialchars($filePath));
}
//echo "<p>Main database file read successfully.</p>";

// Decode the JSON content
$data = @json_decode($content, true);
if ($data === null) {
	handleError('Failed to decode JSON from the main database file. Error: ' . htmlspecialchars(json_last_error_msg()));
}
//echo "<p>Main database JSON decoded successfully.</p>";

// Check if the English translation file exists
if (!file_exists($enFilePath)) {
	// Create the English translation file with default data
	$defaultTranslations = json_encode($data, JSON_PRETTY_PRINT);
	$result = @file_put_contents($enFilePath, $defaultTranslations);
	if ($result === false) {
		handleError('Failed to create the English translation file at ' . htmlspecialchars($enFilePath));
	}
	$message = '<p class="wcc-success">English translation file created successfully.</p>';
	//echo $message;
} else {
	$message = '<p class="wcc-success">English translation file already exists.</p>';
	//echo $message;
}

// Read the English translation file
$enContent = @file_get_contents($enFilePath);
if ($enContent === false) {
	handleError('Failed to read the English translation file at ' . htmlspecialchars($enFilePath));
}
//echo "<p>English translation file read successfully.</p>";

// Decode the JSON content
$enData = @json_decode($enContent, true);
if ($enData === null) {
	handleError('Failed to decode JSON from the English translation file. Error: ' . htmlspecialchars(json_last_error_msg()));
}
//echo "<p>English translation JSON decoded successfully.</p>";

// Initialize a variable for messages
$messages = '';

if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['save_changes'])) {
	// Debugging: Output posted data
	//$messages .= '<pre>Posted data: ' . print_r($_POST, true) . '</pre>';
	//echo "<p>Processing POST request.</p>";

	// Save changes for pages and subpages
	if (isset($_POST['selected_page'])) {
		$selectedPage = $_POST['selected_page'];
		echo "<p>Selected page: " . htmlspecialchars($selectedPage) . "</p>";
		$selectedPageParts = explode('/', $selectedPage);
		$pageKey = $selectedPageParts[0];
		$subpageKey = isset($selectedPageParts[1]) ? $selectedPageParts[1] : '';

		foreach ($_POST as $key => $value) {
			if (strpos($key, 'page_') === 0) {
				$keyParts = explode('_', substr($key, 5));
				$field = array_pop($keyParts);
				$path = $keyParts;
				if ($subpageKey) {
					$path[] = 'subpages';
					$path[] = $subpageKey;
				}
				$path[] = $field;
				//echo "<p>Saving field: " . htmlspecialchars($key) . " with value: " . htmlspecialchars($value) . "</p>";
				setNestedArrayValue($enData['pages'], $path, $value);
			}
		}
	}

	// Save changes for menu items (if required)
	if (isset($_POST['selected_menu_item'])) {
		$selectedMenuItem = $_POST['selected_menu_item'];
		echo "<p>Selected menu item: " . htmlspecialchars($selectedMenuItem) . "</p>";
		if (isset($data['menuItems'][$selectedMenuItem])) {
			foreach ($_POST as $key => $value) {
				if (strpos($key, 'menu_') === 0) {
					$keyParts = explode('_', $key);
					if (count($keyParts) === 3 && $keyParts[0] === 'menu' && $keyParts[1] === $selectedMenuItem) {
						$field = $keyParts[2];
						if (isset($enData['menuItems'][$selectedMenuItem][$field])) {
							echo "<p>Updating menu item field: " . htmlspecialchars($field) . " with value: " . htmlspecialchars($value) . "</p>";
							$enData['menuItems'][$selectedMenuItem][$field] = $value;
						}
					}
				}
			}
		} else {
			$messages .= '<p class="wcc-error">Selected menu item does not exist.</p>';
			echo $messages;
		}
	}

	// Save the updated data
	$jsonData = json_encode($enData, JSON_PRETTY_PRINT);
	//echo "<p>Saving updated English translation data.</p>";
	$result = @file_put_contents($enFilePath, $jsonData);
	if ($result === false) {
		$messages .= '<p class="wcc-error">Failed to save changes to the English translation file.</p>';
		echo $messages;
	} else {
		$messages .= '<p class="wcc-success">Changes saved successfully.</p>';
		echo $messages;
	}
}

// Function to generate HTML for text areas
function generateTextArea($name, $frValue, $enValue) {
	//echo "<p>Generating text area for: " . htmlspecialchars($name) . "</p>";
	return '<label for="' . htmlspecialchars($name) . '">' . htmlspecialchars($name) . ':</label><br>
			<div style="display: flex;">
				<div style="flex: 1; padding-right: 10px;">
					<strong>French:</strong><br>
					<textarea id="' . htmlspecialchars($name) . '_fr" rows="5" cols="50" readonly>' . htmlspecialchars($frValue) . '</textarea>
				</div>
				<div style="flex: 1;">
					<strong>English:</strong><br>
					<textarea id="' . htmlspecialchars($name) . '_en" name="' . htmlspecialchars($name) . '" rows="5" cols="50">' . htmlspecialchars($enValue) . '</textarea>
				</div>
			</div>
			<br><br>';
}

// Output HTML form with data
?>
<!DOCTYPE html>
<html lang='en'>
<head>
	<meta charset='UTF-8'>
	<meta name='viewport' content='width=device-width, initial-scale=1.0'>
	<title>Translation Editor</title>
	<style>
		.wcc-error { color: red; }
		.wcc-success { color: green; }
	</style>
	<link rel="stylesheet" as="style" rel="preload" href="https://dorianchapeau.com/themes/dc/css/dc_style.css">
</head>
<body>
	<h2>Translate Content</h2>
	<form method='post'>
		<!-- Dropdown menu for page selection -->
		<label for='selected_page'>Select Page:</label>
		<select id='selected_page' name='selected_page' onchange='this.form.submit()'>
			<?php
			function generatePageOptions($pages, $selected = '') {
				echo "<p>Generating page options.</p>";
				$options = "<option value=''>-- Select a Page --</option>";
				foreach ($pages as $key => $page) {
					$options .= "<option value='" . htmlspecialchars($key) . "'" . ($selected == $key ? " selected" : "") . ">" . htmlspecialchars($key) . "</option>";
					if (isset($page['subpages']) && is_array($page['subpages'])) {
						foreach ($page['subpages'] as $subpageKey => $subpage) {
							$options .= "<option value='" . htmlspecialchars($key) . '/' . htmlspecialchars($subpageKey) . "'" . ($selected == $key . '/' . $subpageKey ? " selected" : "") . ">-- " . htmlspecialchars($subpageKey) . "</option>";
						}
					}
				}
				return $options;
			}

			echo generatePageOptions($data['pages'], isset($_POST['selected_page']) ? $_POST['selected_page'] : '');
			?>
		</select>
		<br><br><br><input type="submit" name="save_changes" value="Save Changes">

		<?php
		// Display fields for the selected page
		if (isset($_POST['selected_page']) && !empty($_POST['selected_page'])) {
			$selectedPage = $_POST['selected_page'];
			echo "<p>Selected page for editing: " . htmlspecialchars($selectedPage) . "</p>";
			$selectedPageParts = explode('/', $selectedPage);
			$pageKey = $selectedPageParts[0];
			$subpageKey = isset($selectedPageParts[1]) ? $selectedPageParts[1] : '';
		
			// Fetch the French (default language) data
			if (isset($data['pages'][$pageKey])) {
				$pageData = $data['pages'][$pageKey];
				$enPageData = isset($enData['pages'][$pageKey]) ? $enData['pages'][$pageKey] : [];
				
				if ($subpageKey && isset($pageData['subpages'][$subpageKey])) {
					// Handle subpages for the default language
					$pageData = $pageData['subpages'][$subpageKey];
				
					// Ensure you are also correctly navigating the English data structure
					if (isset($enData['pages'][$pageKey]['subpages'][$subpageKey])) {
						$enPageData = $enData['pages'][$pageKey]['subpages'][$subpageKey];
					} else {
						$enPageData = []; // Empty if no translation exists
					}
				}

				echo '<h3>Page: ' . htmlspecialchars($selectedPage) . '</h3>';
		
				// Loop through each field in the French data and find corresponding English data
				foreach ($pageData as $key => $value) {
					if ($key !== 'subpages') {
						$frValue = $value;
						$enValue = isset($enPageData[$key]) ? $enPageData[$key] : '';  // Ensure the subpage key is used here
						echo generateTextArea('page_' . $selectedPage . '_' . $key, $frValue, $enValue);
					}
				}

			} else {
				echo '<p class="wcc-error">Selected page does not exist.</p>';
			}
		}
		?>
		<br><input type="submit" name="save_changes" value="Save Changes">
	</form>
</body>
</html>

At this point, this code could use some serious tweaking I think. The translated for subpages strings do not get populated properly in the translation side of the panel, they show the original language strings. I can't figure out why yet.

I'd love for your guys to try it out, all you need to do it change the path to the database files and put this file on your server. To access the translation panel, just enter the direct URL to the php file you just uploaded.

The next will be figuring out how to let users switch languages and making the cms read the translated version of the db, but I'm nowhere near that step yet.

Any help or recommendations welcome from more expert coders...

Thanks
Post Reply