]> BookStack Code Mirror - bookstack/commitdiff
Created sketchy translation formatter script
authorDan Brown <redacted>
Fri, 14 Dec 2018 21:23:05 +0000 (21:23 +0000)
committerDan Brown <redacted>
Fri, 14 Dec 2018 21:23:05 +0000 (21:23 +0000)
Compares a translation file to a EN version to
place translations on matching line numbers and matches
up comments.

resources/lang/en/activities.php
resources/lang/en/validation.php
resources/lang/format.php [new file with mode: 0755]

index 153ae33f0a6124f6c3199252b72f50e85ff70e6c..4cac54b2a706efa35cb8873ebc247c20420e65b5 100644 (file)
@@ -1,12 +1,10 @@
 <?php
-
+/**
+ * Activity text strings.
+ * Is used for all the text within activity logs & notifications.
+ */
 return [
 
-    /**
-     * Activity text strings.
-     * Is used for all the text within activity logs & notifications.
-     */
-
     // Pages
     'page_create'                 => 'created page',
     'page_create_notification'    => 'Page Successfully Created',
index b75af7485ffb7baf86a2faaf46f6ab4107956a3d..0b6a1c170a5fb31d7d470eedf61bb7a89bd96dbb 100644 (file)
@@ -1,18 +1,13 @@
 <?php
-
+/**
+ * Validation Lines
+ * The following language lines contain the default error messages used by
+ * the validator class. Some of these rules have multiple versions such
+ * as the size rules. Feel free to tweak each of these messages here.
+ */
 return [
 
-    /*
-    |--------------------------------------------------------------------------
-    | Validation Language Lines
-    |--------------------------------------------------------------------------
-    |
-    | The following language lines contain the default error messages used by
-    | the validator class. Some of these rules have multiple versions such
-    | as the size rules. Feel free to tweak each of these messages here.
-    |
-    */
-
+    // Standard laravel validation lines
     'accepted'             => 'The :attribute must be accepted.',
     'active_url'           => 'The :attribute is not a valid URL.',
     'after'                => 'The :attribute must be a date after :date.',
@@ -75,34 +70,13 @@ return [
     'unique'               => 'The :attribute has already been taken.',
     'url'                  => 'The :attribute format is invalid.',
 
-    /*
-    |--------------------------------------------------------------------------
-    | Custom Validation Language Lines
-    |--------------------------------------------------------------------------
-    |
-    | Here you may specify custom validation messages for attributes using the
-    | convention "attribute.rule" to name the lines. This makes it quick to
-    | specify a specific custom language line for a given attribute rule.
-    |
-    */
-
+    // Custom validation lines
     'custom' => [
         'password-confirm' => [
             'required_with' => 'Password confirmation required',
         ],
     ],
 
-    /*
-    |--------------------------------------------------------------------------
-    | Custom Validation Attributes
-    |--------------------------------------------------------------------------
-    |
-    | The following language lines are used to swap attribute place-holders
-    | with something more reader friendly such as E-Mail Address instead
-    | of "email". This simply helps us make messages a little cleaner.
-    |
-    */
-
+    // Custom validation attributes
     'attributes' => [],
-
 ];
diff --git a/resources/lang/format.php b/resources/lang/format.php
new file mode 100755 (executable)
index 0000000..8698d1b
--- /dev/null
@@ -0,0 +1,201 @@
+#!/usr/bin/env php
+<?php
+
+/**
+ * Format a language file in the same way as the EN equivalent.
+ * Matches the line numbers of translated content.
+ */
+
+$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)");
+}
+
+$lang = formatLang($args[0]);
+$fileName = explode('.', $args[1])[0];
+
+$enLines = loadLangFileLines('en', $fileName);
+$langContent = loadLang($lang, $fileName);
+$enContent = loadLang('en', $fileName);
+
+// Calculate the longest top-level key length
+$longestKeyLength = longestKey($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';
+    }
+
+    if ($mode === 'body') {
+        $matches = [];
+
+        // 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);
+            $key = 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 = 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[] = '];';
+$formatted = implode("\n", $formatted);
+
+writeLangFile($lang, $fileName, $formatted);
+
+function formatTranslationLine(string $key, string $value, int $indent = 1, int $keyPad = 1) {
+    $escapedValue = str_replace("'", "\\'", $value);
+    return str_repeat(" ", $indent * 4) . str_pad("'{$key}'", $keyPad, ' ') ."=> '{$escapedValue}',";
+}
+
+function longestKey(array $array) {
+    $top = 0;
+    foreach ($array as $key => $value) {
+        $keyLen = strlen($key);
+        $top = max($top, $keyLen);
+    }
+    return $top + 3;
+}
+
+function formatTranslationArray(string $key, array $array) {
+    $arrayPHP = var_export($array, true);
+    return "    '{$key}' => {$arrayPHP},";
+}
+
+function getTranslationByKeys(array $translations, array $keys) {
+    $val = $translations;
+    foreach ($keys as $key) {
+        $val = $val[$key] ?? '';
+        if ($val === '') return '';
+    }
+    return $val;
+}
+
+function unsetArrayByKeys(array &$input, array $keys) {
+    $val = &$input;
+    $lastIndex = count($keys) - 1;
+    foreach ($keys as $index => &$key) {
+        if ($index === $lastIndex && is_array($val)) {
+            unset($val[$key]);
+        }
+        if (!is_array($val)) return;
+        $val = &$val[$key] ?? [];
+    }
+}
+
+function writeLangFile(string $lang, string $fileName, string $content) {
+    $path = __DIR__ . "/{$lang}/{$fileName}.php";
+    if (!file_exists($path)) {
+        errorOut("Expected translation file '{$path}' does not exist");
+    }
+    file_put_contents($path, $content);
+}
+
+function loadLangFileLines(string $lang, string $fileName) {
+    $path = __DIR__ . "/{$lang}/{$fileName}.php";
+    if (!file_exists($path)) {
+        errorOut("Expected translation file '{$path}' does not exist");
+    }
+    $lines = explode("\n", file_get_contents($path));
+    return array_map(function($line) {
+        return trim($line, "\r");
+    }, $lines);
+}
+
+function loadLang(string $lang, string $fileName) {
+    $path = __DIR__ . "/{$lang}/{$fileName}.php";
+    if (!file_exists($path)) {
+        errorOut("Expected translation file '{$path}' does not exist");
+    }
+
+    $fileData = include($path);
+    return $fileData;
+}
+
+function formatLang($lang) {
+    $langParts = explode('_', strtoupper($lang));
+    $langParts[0] = strtolower($langParts[0]);
+    return implode('_', $langParts);
+}
+
+function dd($content) {
+    print_r($content);
+    exit(1);
+}
+
+function info($text) {
+    echo "\e[34m" . $text . "\e[0m\n";
+}
+
+function errorOut($text) {
+    echo "\e[31m" . $text . "\e[0m\n";
+    exit(1);
+}
\ No newline at end of file