mirror of
https://github.com/BookStackApp/BookStack.git
synced 2025-05-31 21:23:38 +08:00
Cleaned up script and formatted remaining EN files
This commit is contained in:
@ -4,119 +4,150 @@
|
||||
/**
|
||||
* 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);
|
||||
|
||||
foreach($enLines as $index => $line) {
|
||||
$trimLine = trim($line);
|
||||
if ($mode === 'header') {
|
||||
$formatted[$index] = $line;
|
||||
if (str_replace(' ', '', $trimLine) === 'return[') $mode = 'body';
|
||||
}
|
||||
// Calculate the longest top-level key length
|
||||
$longestKeyLength = calculateKeyPadding($enContent);
|
||||
|
||||
if ($mode === 'body') {
|
||||
$matches = [];
|
||||
// Start formatted content
|
||||
$formatted = [];
|
||||
$mode = 'header';
|
||||
$arrayKeys = [];
|
||||
|
||||
// Comment
|
||||
if (strpos($trimLine, '//') === 0) {
|
||||
$formatted[$index] = "\t" . $trimLine;
|
||||
continue;
|
||||
foreach($enLines as $index => $line) {
|
||||
$trimLine = trim($line);
|
||||
if ($mode === 'header') {
|
||||
$formatted[$index] = $line;
|
||||
if (str_replace(' ', '', $trimLine) === 'return[') $mode = 'body';
|
||||
}
|
||||
|
||||
// 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) . "],";
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if ($mode === 'body') {
|
||||
$matches = [];
|
||||
|
||||
// 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));
|
||||
// Comment
|
||||
if (strpos($trimLine, '//') === 0) {
|
||||
$formatted[$index] = "\t" . $trimLine;
|
||||
continue;
|
||||
}
|
||||
|
||||
$formatted[$index] = formatTranslationLine($key, $langVal, $indent, $keyPad);
|
||||
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;
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// 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);
|
||||
@ -125,12 +156,27 @@ function longestKey(array $array) {
|
||||
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] ?? '';
|
||||
@ -139,6 +185,12 @@ function getTranslationByKeys(array $translations, array $keys) {
|
||||
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;
|
||||
@ -151,6 +203,12 @@ function unsetArrayByKeys(array &$input, array $keys) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)) {
|
||||
@ -159,7 +217,13 @@ function writeLangFile(string $lang, string $fileName, string $content) {
|
||||
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");
|
||||
@ -170,7 +234,13 @@ function loadLangFileLines(string $lang, string $fileName) {
|
||||
}, $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");
|
||||
@ -180,21 +250,57 @@ function loadLang(string $lang, string $fileName) {
|
||||
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);
|
||||
|
Reference in New Issue
Block a user