<?php
+/**
+ * Text used for 'Entities' (Document Structure Elements) such as
+ * Books, Shelves, Chapters & Pages
+ */
return [
- /**
- * Shared
- */
+ // Shared
'recently_created' => 'Recently Created',
'recently_created_pages' => 'Recently Created Pages',
'recently_updated_pages' => 'Recently Updated Pages',
'export_pdf' => 'PDF File',
'export_text' => 'Plain Text File',
- /**
- * Permissions and restrictions
- */
+ // Permissions and restrictions
'permissions' => 'Permissions',
'permissions_intro' => 'Once enabled, These permissions will take priority over any set role permissions.',
'permissions_enable' => 'Enable Custom Permissions',
'permissions_save' => 'Save Permissions',
- /**
- * Search
- */
+ // Search
'search_results' => 'Search Results',
'search_total_results_found' => ':count result found|:count total results found',
'search_clear' => 'Clear Search',
'search_set_date' => 'Set Date',
'search_update' => 'Update Search',
- /**
- * Shelves
- */
+ // Shelves
'shelf' => 'Shelf',
'shelves' => 'Shelves',
'shelves_long' => 'Bookshelves',
'shelves_copy_permissions_explain' => 'This will apply the current permission settings of this bookshelf to all books contained within. Before activating, ensure any changes to the permissions of this bookshelf have been saved.',
'shelves_copy_permission_success' => 'Bookshelf permissions copied to :count books',
- /**
- * Books
- */
+ // Books
'book' => 'Book',
'books' => 'Books',
'x_books' => ':count Book|:count Books',
'books_sort_show_other' => 'Show Other Books',
'books_sort_save' => 'Save New Order',
- /**
- * Chapters
- */
+ // Chapters
'chapter' => 'Chapter',
'chapters' => 'Chapters',
'x_chapters' => ':count Chapter|:count Chapters',
'chapters_permissions_success' => 'Chapter Permissions Updated',
'chapters_search_this' => 'Search this chapter',
- /**
- * Pages
- */
+ // Pages
'page' => 'Page',
'pages' => 'Pages',
'x_pages' => ':count Page|:count Pages',
'pages_draft_discarded' => 'Draft discarded, The editor has been updated with the current page content',
'pages_specific' => 'Specific Page',
- /**
- * Editor sidebar
- */
+ // Editor Sidebar
'page_tags' => 'Page Tags',
'chapter_tags' => 'Chapter Tags',
'book_tags' => 'Book Tags',
'attachments_file_updated' => 'File successfully updated',
'attachments_link_attached' => 'Link successfully attached to page',
- /**
- * Profile View
- */
+ // Profile View
'profile_user_for_x' => 'User for :time',
'profile_created_content' => 'Created Content',
'profile_not_created_pages' => ':userName has not created any pages',
'profile_not_created_chapters' => ':userName has not created any chapters',
'profile_not_created_books' => ':userName has not created any books',
- /**
- * Comments
- */
+ // Comments
'comment' => 'Comment',
'comments' => 'Comments',
'comment_add' => 'Add Comment',
'comment_delete_confirm' => 'Are you sure you want to delete this comment?',
'comment_in_reply_to' => 'In reply to :commentId',
- /**
- * Revision
- */
+ // Revision
'revision_delete_confirm' => 'Are you sure you want to delete this revision?',
'revision_delete_success' => 'Revision deleted',
'revision_cannot_delete_latest' => 'Cannot delete the latest revision.'
/**
* Format a language file in the same way as the EN equivalent.
* Matches the line numbers of translated content.
+ * Potentially destructive, Ensure you have a backup of your translation content before running.
*/
$args = array_slice($argv, 1);
if (count($args) < 2) {
- errorOut("Please provide a language code as the first argument and a translation file name as the second (./format.php fr activities)");
+ errorOut("Please provide a language code as the first argument and a translation file name, or '--all', as the second (./format.php fr activities)");
}
-$lang = formatLang($args[0]);
+$lang = formatLocale($args[0]);
$fileName = explode('.', $args[1])[0];
+$filesNames = [$fileName];
+if ($fileName === '--all') {
+ $fileNames = getTranslationFileNames();
+}
-$enLines = loadLangFileLines('en', $fileName);
-$langContent = loadLang($lang, $fileName);
-$enContent = loadLang('en', $fileName);
+foreach ($fileNames as $fileName) {
+ $formatted = formatFileContents($lang, $fileName);
+ writeLangFile($lang, $fileName, $formatted);
+}
-// Calculate the longest top-level key length
-$longestKeyLength = longestKey($enContent);
-// Start formatted content
-$formatted = [];
-$mode = 'header';
-$arrayKeys = [];
+/**
+ * Format the contents of a single translation file in the given language.
+ * @param string $lang
+ * @param string $fileName
+ * @return string
+ */
+function formatFileContents(string $lang, string $fileName) : string {
+ $enLines = loadLangFileLines('en', $fileName);
+ $langContent = loadLang($lang, $fileName);
+ $enContent = loadLang('en', $fileName);
+
+ // Calculate the longest top-level key length
+ $longestKeyLength = calculateKeyPadding($enContent);
+
+ // Start formatted content
+ $formatted = [];
+ $mode = 'header';
+ $arrayKeys = [];
+
+ foreach($enLines as $index => $line) {
+ $trimLine = trim($line);
+ if ($mode === 'header') {
+ $formatted[$index] = $line;
+ if (str_replace(' ', '', $trimLine) === 'return[') $mode = 'body';
+ }
-foreach($enLines as $index => $line) {
- $trimLine = trim($line);
- if ($mode === 'header') {
- $formatted[$index] = $line;
- if (str_replace(' ', '', $trimLine) === 'return[') $mode = 'body';
- }
+ if ($mode === 'body') {
+ $matches = [];
- if ($mode === 'body') {
- $matches = [];
+ // Comment
+ if (strpos($trimLine, '//') === 0) {
+ $formatted[$index] = "\t" . $trimLine;
+ continue;
+ }
- // Comment
- if (strpos($trimLine, '//') === 0) {
- $formatted[$index] = "\t" . $trimLine;
- continue;
- }
+ // Arrays
+ $arrayStartMatch = preg_match('/^\'(.*)\'\s+?=>\s+?\[(\],)?\s*?$/', $trimLine, $matches);
+ $arrayEndMatch = preg_match('/]\s*,\s*$/', $trimLine);
+ $indent = count($arrayKeys) + 1;
+ if ($arrayStartMatch === 1) {
+ $arrayKeys[] = $matches[1];
+ $formatted[$index] = str_repeat(" ", $indent * 4) . str_pad("'{$matches[1]}'", $longestKeyLength) . "=> [";
+ if ($arrayEndMatch !== 1) continue;
+ }
+ if ($arrayEndMatch === 1) {
+ unsetArrayByKeys($langContent, $arrayKeys);
+ array_pop($arrayKeys);
+ if (isset($formatted[$index])) {
+ $formatted[$index] .= '],';
+ } else {
+ $formatted[$index] = str_repeat(" ", ($indent-1) * 4) . "],";
+ }
+ continue;
+ }
- // Arrays
- $arrayStartMatch = preg_match('/^\'(.*)\'\s+?=>\s+?\[(\],)?\s*?$/', $trimLine, $matches);
- $arrayEndMatch = preg_match('/]\s*,\s*$/', $trimLine);
- $indent = count($arrayKeys) + 1;
- if ($arrayStartMatch === 1) {
- $arrayKeys[] = $matches[1];
- $formatted[$index] = str_repeat(" ", $indent * 4) . str_pad("'{$matches[1]}'", $longestKeyLength) . "=> [";
- if ($arrayEndMatch !== 1) continue;
- }
- if ($arrayEndMatch === 1) {
- unsetArrayByKeys($langContent, $arrayKeys);
- $key = array_pop($arrayKeys);
- if (isset($formatted[$index])) {
- $formatted[$index] .= '],';
- } else {
- $formatted[$index] = str_repeat(" ", ($indent-1) * 4) . "],";
+ // Translation
+ $translationMatch = preg_match('/^\'(.*)\'\s+?=>\s+?\'(.*)?\'.+?$/', $trimLine, $matches);
+ if ($translationMatch === 1) {
+ $key = $matches[1];
+ $keys = array_merge($arrayKeys, [$key]);
+ $langVal = getTranslationByKeys($langContent, $keys);
+ if (empty($langVal)) continue;
+
+ $keyPad = $longestKeyLength;
+ if (count($arrayKeys) === 0) {
+ unset($langContent[$key]);
+ } else {
+ $keyPad = calculateKeyPadding(getTranslationByKeys($enContent, $arrayKeys));
+ }
+
+ $formatted[$index] = formatTranslationLine($key, $langVal, $indent, $keyPad);
+ continue;
}
- continue;
}
- // Translation
- $translationMatch = preg_match('/^\'(.*)\'\s+?=>\s+?\'(.*)?\'.+?$/', $trimLine, $matches);
- if ($translationMatch === 1) {
- $key = $matches[1];
- $keys = array_merge($arrayKeys, [$key]);
- $langVal = getTranslationByKeys($langContent, $keys);
- if (empty($langVal)) continue;
-
- $keyPad = $longestKeyLength;
- if (count($arrayKeys) === 0) {
- unset($langContent[$key]);
- } else {
- $keyPad = longestKey(getTranslationByKeys($enContent, $arrayKeys));
- }
+ }
- $formatted[$index] = formatTranslationLine($key, $langVal, $indent, $keyPad);
- continue;
+ // Fill missing lines
+ $arraySize = max(array_keys($formatted));
+ $formatted = array_replace(array_fill(0, $arraySize, ''), $formatted);
+
+ // Add remaining translations
+ $langContent = array_filter($langContent, function($item) {
+ return !is_null($item) && !empty($item);
+ });
+ if (count($langContent) > 0) {
+ $formatted[] = '';
+ $formatted[] = "\t// Unmatched";
+ }
+ foreach ($langContent as $key => $value) {
+ if (is_array($value)) {
+ $formatted[] = formatTranslationArray($key, $value);
+ } else {
+ $formatted[] = formatTranslationLine($key, $value);
}
}
+ // Add end line
+ $formatted[] = '];';
+ return implode("\n", $formatted);
}
-// Fill missing lines
-$arraySize = max(array_keys($formatted));
-$formatted = array_replace(array_fill(0, $arraySize, ''), $formatted);
-
-// Add remaining translations
-$langContent = array_filter($langContent, function($item) {
- return !is_null($item) && !empty($item);
-});
-if (count($langContent) > 0) {
- $formatted[] = '';
- $formatted[] = "\t// Unmatched";
-}
-foreach ($langContent as $key => $value) {
- if (is_array($value)) {
- $formatted[] = formatTranslationArray($key, $value);
- } else {
- $formatted[] = formatTranslationLine($key, $value);
- }
-}
-
-// Add end line
-$formatted[] = '];';
-$formatted = implode("\n", $formatted);
-
-writeLangFile($lang, $fileName, $formatted);
-
-function formatTranslationLine(string $key, string $value, int $indent = 1, int $keyPad = 1) {
+/**
+ * Format a translation line.
+ * @param string $key
+ * @param string $value
+ * @param int $indent
+ * @param int $keyPad
+ * @return string
+ */
+function formatTranslationLine(string $key, string $value, int $indent = 1, int $keyPad = 1) : string {
$escapedValue = str_replace("'", "\\'", $value);
return str_repeat(" ", $indent * 4) . str_pad("'{$key}'", $keyPad, ' ') ."=> '{$escapedValue}',";
}
-function longestKey(array $array) {
+/**
+ * Find the longest key in the array and provide the length
+ * for all keys to be used when printed.
+ * @param array $array
+ * @return int
+ */
+function calculateKeyPadding(array $array) : int {
$top = 0;
foreach ($array as $key => $value) {
$keyLen = strlen($key);
return $top + 3;
}
-function formatTranslationArray(string $key, array $array) {
+/**
+ * Format an translation array with the given key.
+ * Simply prints as an old-school php array.
+ * Used as a last-resort backup to save unused translations.
+ * @param string $key
+ * @param array $array
+ * @return string
+ */
+function formatTranslationArray(string $key, array $array) : string {
$arrayPHP = var_export($array, true);
return " '{$key}' => {$arrayPHP},";
}
-function getTranslationByKeys(array $translations, array $keys) {
+/**
+ * Find a string translation value within a multi-dimensional array
+ * by traversing the given array of keys.
+ * @param array $translations
+ * @param array $keys
+ * @return string|array
+ */
+function getTranslationByKeys(array $translations, array $keys) {
$val = $translations;
foreach ($keys as $key) {
$val = $val[$key] ?? '';
return $val;
}
+/**
+ * Unset an inner item of a multi-dimensional array by
+ * traversing the given array of keys.
+ * @param array $input
+ * @param array $keys
+ */
function unsetArrayByKeys(array &$input, array $keys) {
$val = &$input;
$lastIndex = count($keys) - 1;
}
}
+/**
+ * Write the given content to a translation file.
+ * @param string $lang
+ * @param string $fileName
+ * @param string $content
+ */
function writeLangFile(string $lang, string $fileName, string $content) {
$path = __DIR__ . "/{$lang}/{$fileName}.php";
if (!file_exists($path)) {
file_put_contents($path, $content);
}
-function loadLangFileLines(string $lang, string $fileName) {
+/**
+ * Load the contents of a language file as an array of text lines.
+ * @param string $lang
+ * @param string $fileName
+ * @return array
+ */
+function loadLangFileLines(string $lang, string $fileName) : array {
$path = __DIR__ . "/{$lang}/{$fileName}.php";
if (!file_exists($path)) {
errorOut("Expected translation file '{$path}' does not exist");
}, $lines);
}
-function loadLang(string $lang, string $fileName) {
+/**
+ * Load the contents of a language file
+ * @param string $lang
+ * @param string $fileName
+ * @return array
+ */
+function loadLang(string $lang, string $fileName) : array {
$path = __DIR__ . "/{$lang}/{$fileName}.php";
if (!file_exists($path)) {
errorOut("Expected translation file '{$path}' does not exist");
return $fileData;
}
-function formatLang($lang) {
+/**
+ * Fetch an array containing the names of all translation files without the extension.
+ * @return array
+ */
+function getTranslationFileNames() : array {
+ $dir = __DIR__ . "/en";
+ if (!file_exists($dir)) {
+ errorOut("Expected directory '{$dir}' does not exist");
+ }
+ $files = scandir($dir);
+ $fileNames = [];
+ foreach ($files as $file) {
+ if (substr($file, -4) === '.php') {
+ $fileNames[] = substr($file, 0, strlen($file) - 4);
+ }
+ }
+ return $fileNames;
+}
+
+/**
+ * Format a locale to follow the lowercase_UPERCASE standard
+ * @param string $lang
+ * @return string
+ */
+function formatLocale(string $lang) : string {
$langParts = explode('_', strtoupper($lang));
$langParts[0] = strtolower($langParts[0]);
return implode('_', $langParts);
}
+/**
+ * Dump a variable then die.
+ * @param $content
+ */
function dd($content) {
print_r($content);
exit(1);
}
+/**
+ * Log out some information text in blue
+ * @param $text
+ */
function info($text) {
echo "\e[34m" . $text . "\e[0m\n";
}
+/**
+ * Log out an error in red and exit.
+ * @param $text
+ */
function errorOut($text) {
echo "\e[31m" . $text . "\e[0m\n";
exit(1);