source: trunk/contrib/lc_split_merged_file.php @ 1404

Last change on this file since 1404 was 1404, checked in by gogo, 20 months ago

Setup to sort the language data files properly by key, I meant to do that before committing the big patch.

File size: 7.1 KB
Line 
1<?php
2  /** Parse a master translation file for a given language
3   *   and create a directory containing split translation files
4   *   for each module.
5   *
6   * Essentially the opposite of lc_create_merged_file.php
7   *  note that this does not overwrite the existing language files
8   *  it creates new ones in a new directory.
9   *
10   * You can then use diff to compare the results before you copy
11   *  them over.
12   */
13   
14
15  $InFile = $argv[1];
16  $TargetLanguage = $argv[2];
17
18  function usage()
19  {
20    global $argv;
21    echo "Usage: ";
22    echo $argv[0] . ' /path/to/fr.js fr [outputdirectory]' . "\n\n";
23   
24    echo " Output directory defaults to a new unique directory in /tmp\n\n";
25   
26    echo "PROTIP: To split all language files in lang/merged/*.js you can do...
27   
28    if ! [ -f XinhaCore.js ] ; then cd ../; fi
29    OUTDIR=\"/tmp/lang-output-$(date -u | sed -r 's/ /-/g')\"
30    mkdir \$OUTDIR
31    for file in lang/merged/*.js
32    do
33      if ! [ \"$(basename \$file)\" = \"__new__.js\" ]
34      then
35        php contrib/".basename($argv[0])." \$file \"\$(basename \$file | sed -r 's/\.js//')\" \$OUTDIR
36      fi
37    done
38
39";
40    exit;
41  }
42   
43  if(!file_exists($InFile) || !strlen($TargetLanguage))
44  {
45    usage();
46  }
47
48  $OutDir = $argv[3] ? $argv[3] : uniqid('/tmp/xinha-lang-import-');
49  @mkdir($OutDir);
50 
51  $XinhaRoot = realpath(dirname(__FILE__).'/..');
52 
53  $languageDirs = array(
54    $XinhaRoot.'/lang',
55  );
56 
57  function load_lang_file($file)
58  {
59    if(!file_exists($file)) return array();
60   
61    $contents = file_get_contents($file);
62    // Remove comments
63    $contents = preg_replace('/^(\xEF\xBB\xBF)?\s*\/\/.*$/m', '', trim($contents));
64    $contents = preg_replace('/\/\*.*?\*\//s', '', $contents);
65   
66    $contents= trim(trim(trim($contents),';'));
67   
68    file_put_contents('/tmp/o', $contents);
69    $decode = json_decode($contents, true);
70   
71    if(!$decode)
72    {
73      //JSON only doubel quotes
74      $contents = preg_replace_callback('/^(\s*)\'(([^\']|\\\\\')+?)\'(\s*:)/m', function($m){
75        $m[2] =  preg_replace('/\\\\\'/', '\'', $m[2]);
76        $m[2] = preg_replace('/"/', '\\"',$m[2]);
77        return $m[1].'"'.$m[2].'"'.$m[4];
78      }, $contents);
79     
80      $contents = preg_replace_callback('/^(\s*"(?:[^"]|\\\\")+?"\s*:\s*)\'(([^\']|\\\\\')+)(\s*)\'/m', function($m){
81        $m[2] =  preg_replace('/\\\\\'/', '\'', $m[2]);
82        $m[2] = preg_replace('/"/', '\\"',$m[2]);
83        return $m[1].'"'.$m[2].'"'.$m[4];
84      }, $contents);
85     
86      // Escaped singles are forbidden?
87      $contents = preg_replace('/\\\\\'/', "'", $contents);
88     
89      $contents= trim(trim(trim($contents),';'));
90      $decode = json_decode($contents, true);
91    }
92   
93    if(!$decode)
94    {
95      echo $contents;
96      throw new Exception("Decode of {$file} failed. " . json_last_error());
97    }
98    return $decode;
99  }
100
101  $Data = load_lang_file($InFile);
102 
103  // Merge the __NEW_TRANSLATIONS__ section
104  foreach(array_keys($Data['__NEW_TRANSLATIONS__']) as $moduleName)
105  {
106    foreach($Data['__NEW_TRANSLATIONS__'][$moduleName] as $englishString => $localString)
107    {
108      if(preg_match('/<<([a-z0-9_-]+)>>/i', $localString, $M))
109      {
110        $localString = @$Data[$M[1]][$englishString];
111      }
112     
113      if($localString && $localString[0] == '<')
114      {
115          die("Unable to find reference for {$localString}");
116      }
117     
118      if(strlen($localString))
119      {
120        $Data[$moduleName][$englishString] = $localString;
121      }
122    }
123  }
124 
125  // Done with that now
126  unset($Data['__NEW_TRANSLATIONS__']);
127 
128  foreach($Data as $moduleName => $Data)
129  {
130    // Where is it
131    if($moduleName == 'Xinha')
132    {
133      $langFile = 'lang/'.$TargetLanguage.'.js';
134    }
135    elseif(file_exists($XinhaRoot.'/modules/'.$moduleName))
136    {
137      $langFile = 'modules/'.$moduleName.'/lang/'.$TargetLanguage.'.js';
138    }
139    elseif(file_exists($XinhaRoot.'/plugins/'.$moduleName))
140    {
141      $langFile = 'plugins/'.$moduleName.'/lang/'.$TargetLanguage.'.js';
142    }
143    elseif(file_exists($XinhaRoot.'/unsupported_plugins/'.$moduleName))
144    {
145      $langFile = 'unsupported_plugins/'.$moduleName.'/lang/'.$TargetLanguage.'.js';
146    }
147    else
148    {
149      echo "I don't know where to put {$moduleName} for {$TargetLanguage}.";
150      continue;
151    }
152   
153    // Load the existing one if there is and find any obsoleted strings
154    if(file_exists($XinhaRoot . '/'.$langFile))
155    {
156      $obsoleteStrings = array();
157      $existingFile = load_lang_file($XinhaRoot . '/'.$langFile);
158      if(isset($existingFile['__OBSOLETE__']))
159      {
160        // Roll obsoletes back in to be picked up again
161        $existingFile = array_merge($existingFile['__OBSOLETE__']);
162        unset($existingFile['__OBSOLETE__']);
163      }
164     
165      // if the existing file string isn't in the new data
166      // it is obsolete
167      foreach($existingFile as $English=>$Local)
168      {
169        if(!isset($Data[$English]))
170        {
171          $obsoleteStrings[$English] = $Local;
172        }
173      }
174     
175      // Remove any note
176      unset($Data['__ TRANSLATOR NOTE __']);
177     
178      // Sort on the key (english text)
179      ksort($Data);
180     
181      // Push those obsoletes into the data so marked
182      if(count($obsoleteStrings))
183      {
184        ksort($obsoleteStrings);
185        $Data['__OBSOLETE__'] = $obsoleteStrings;
186      }
187     
188      // Resort so that the existing data order is preserved
189      //  if possible
190      /* Nope, don't do this, we will just make a clean break of it
191         and have everything alpha sorted
192         
193          $newData = array();
194          foreach(array_keys($existingFile) as $English)
195          {
196            if(isset($Data[$English]))
197            {
198              $newData[$English] = $Data[$English];
199              unset($Data[$English]);
200            }
201          }
202          foreach(array_keys($Data) as $English)
203          {
204            $newData[$English] = $Data[$English];
205            unset($Data[$English]);
206          }
207          $Data = $newData;
208      */
209     
210    }
211   
212    $Dest = $OutDir . '/'. $langFile;
213    if(!file_exists(dirname($Dest)))
214    {
215      mkdir(dirname($Dest), 0777, true);
216    }
217   
218    $outputData = "// I18N constants
219// LANG: \"{$TargetLanguage}\", ENCODING: UTF-8
220//
221// IMPORTANT NOTICE FOR TRANSLATORS
222// ============================================================================
223//
224// Please be sure you read the README_TRANSLATORS.TXT in the Xinha Root
225// Directory.  Unless you are making a new plugin or module it is unlikely
226// that you want to be editing this file directly.
227//
228".json_encode($Data, JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES|JSON_UNESCAPED_UNICODE).';';
229    file_put_contents($Dest, $outputData);
230  }
231 
232  echo "Parsing complete, files have been written to: $OutDir\n";
233  echo "You should now inspect those files and copy to the Xinha directory tree as appropriate.\n";
234  echo "If this is a half decent Unix type system, you can do something like this to copy everything over blindly.\n";
235  echo
236"
237    for file in $(find $OutDir -type f)
238    do
239      target=" . dirname(dirname(__FILE__)) . "$(echo \$file | sed -r 's/^.*".(basename($OutDir))."//')
240      echo \"Installing: \$file -> \$target\"
241      cp \$file \$target
242    done
243";
244  echo "\n";
245?>
Note: See TracBrowser for help on using the repository browser.