Commit 2f19de11 authored by Thomas Müller's avatar Thomas Müller

adding console command to generate javascript translation files based on...

adding console command to generate javascript translation files based on existing php translation files
read server side translations from json files
parent d71cd680
<?php
/**
* Copyright (c) 2013 Robin Appelman <icewind@owncloud.com> and
* Copyright (c) 2014 Stephen Colebrook <scolebrook@mac.com>
* This file is licensed under the Affero General Public License version 3 or
* later.
* See the COPYING-README file.
*/
namespace OC\Core\Command\L10n;
use DirectoryIterator;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
class CreateJs extends Command {
protected function configure() {
$this
->setName('l10n:createjs')
->setDescription('Create javascript translation files for a given app')
->addArgument(
'app',
InputOption::VALUE_REQUIRED,
'name of the app'
)
->addArgument(
'lang',
InputOption::VALUE_OPTIONAL,
'name of the language'
);
}
protected function execute(InputInterface $input, OutputInterface $output) {
$app = $input->getArgument('app');
$lang = $input->getArgument('lang');
$path = \OC_App::getAppPath($app);
if ($path === false) {
$output->writeln("The app <$app> is unknown.");
return;
}
$languages = $lang;
if (empty($lang)) {
$languages= $this->getAllLanguages($path);
}
foreach($languages as $lang) {
$this->writeFiles($app, $path, $lang, $output);
}
}
private function getAllLanguages($path) {
$result = array();
foreach (new DirectoryIterator("$path/l10n") as $fileInfo) {
if($fileInfo->isDot()) {
continue;
}
if($fileInfo->isDir()) {
continue;
}
if($fileInfo->getExtension() !== 'php') {
continue;
}
$result[]= substr($fileInfo->getBasename(), 0, -4);
}
return $result;
}
private function writeFiles($app, $path, $lang, OutputInterface $output) {
list($translations, $plurals) = $this->loadTranslations($path, $lang);
$this->writeJsFile($app, $path, $lang, $output, $translations, $plurals);
$this->writeJsonFile($path, $lang, $output, $translations, $plurals);
}
private function writeJsFile($app, $path, $lang, OutputInterface $output, $translations, $plurals) {
$jsFile = "$path/l10n/$lang.js";
if (file_exists($jsFile)) {
$output->writeln("File already exists: $jsFile");
return;
}
$content = "OC.L10N.register(\n \"$app\",\n {\n ";
$jsTrans = array();
foreach ($translations as $id => $val) {
if (is_array($val)) {
$val = '[ ' . join(',', $val) . ']';
}
$jsTrans[] = "\"$id\" : \"$val\"";
}
$content .= join(",\n ", $jsTrans);
$content .= "\n},\n\"$plurals\");\n";
file_put_contents($jsFile, $content);
$output->writeln("Javascript translation file generated: $jsFile");
}
private function writeJsonFile($path, $lang, OutputInterface $output, $translations, $plurals) {
$jsFile = "$path/l10n/$lang.json";
if (file_exists($jsFile)) {
$output->writeln("File already exists: $jsFile");
return;
}
$content = array('translations' => $translations, 'pluralForm' => $plurals);
file_put_contents($jsFile, json_encode($content));
$output->writeln("Json translation file generated: $jsFile");
}
private function loadTranslations($path, $lang) {
$phpFile = "$path/l10n/$lang.php";
$TRANSLATIONS = array();
$PLURAL_FORMS = '';
require $phpFile;
return array($TRANSLATIONS, $PLURAL_FORMS);
}
}
......@@ -22,4 +22,5 @@ $application->add(new OC\Core\Command\Maintenance\Repair($repair, OC_Config::get
$application->add(new OC\Core\Command\User\Report());
$application->add(new OC\Core\Command\User\ResetPassword(\OC::$server->getUserManager()));
$application->add(new OC\Core\Command\User\LastSeen());
$application->add(new OC\Core\Command\L10n\CreateJs());
......@@ -120,7 +120,7 @@ if( $task eq 'read' ){
my $language = ( $file =~ /\.js$/ ? 'Python' : 'PHP');
my $joinexisting = ( -e $output ? '--join-existing' : '');
print " Reading $file\n";
`xgettext --output="$output" $joinexisting $keywords --language=$language "$file" --add-comments=TRANSLATORS --from-code=UTF-8 --package-version="6.0.0" --package-name="ownCloud Core" --msgid-bugs-address="translations\@owncloud.org"`;
`xgettext --output="$output" $joinexisting $keywords --language=$language "$file" --add-comments=TRANSLATORS --from-code=UTF-8 --package-version="8.0.0" --package-name="ownCloud Core" --msgid-bugs-address="translations\@owncloud.org"`;
}
chdir( $whereami );
}
......@@ -176,19 +176,24 @@ elsif( $task eq 'write' ){
s/\$/\\\$/g;
}
# Write PHP file
open( OUT, ">$language.php" );
print OUT "<?php\n\$TRANSLATIONS = array(\n";
print OUT join( ",\n", @strings );
print OUT "\n);\n\$PLURAL_FORMS = \"$plurals\";\n";
close( OUT );
# delete old php file
unlink "$language.php";
# Write js file
open( OUT, ">$language.js" );
print OUT "OC.L10N.register(\n \"$app\",\n {\n ";
print OUT join( ",\n ", @js_strings );
print OUT "\n},\n\"$plurals\");\n";
close( OUT );
# Write json file
open( OUT, ">$language.json" );
print OUT "{ \"translations\": ";
print OUT "{\n ";
print OUT join( ",\n ", @js_strings );
print OUT "\n},\"pluralForm\" :\"$plurals\"\n}";
close( OUT );
}
chdir( $whereami );
}
......
......@@ -54,12 +54,12 @@ class OC_L10N implements \OCP\IL10N {
/**
* Plural forms (string)
*/
private $plural_form_string = 'nplurals=2; plural=(n != 1);';
private $pluralFormString = 'nplurals=2; plural=(n != 1);';
/**
* Plural forms (function)
*/
private $plural_form_function = null;
private $pluralFormFunction = null;
/**
* get an L10N instance
......@@ -90,16 +90,26 @@ class OC_L10N implements \OCP\IL10N {
/**
* @param string $transFile
* @return bool
*/
public function load($transFile) {
public function load($transFile, $mergeTranslations = false) {
$this->app = true;
include $transFile;
if(isset($TRANSLATIONS) && is_array($TRANSLATIONS)) {
$this->translations = $TRANSLATIONS;
$json = json_decode(file_get_contents($transFile), true);
if (!is_array($json)) {
return false;
}
if(isset($PLURAL_FORMS)) {
$this->plural_form_string = $PLURAL_FORMS;
$this->pluralFormString = $json['pluralForm'];
$translations = $json['translations'];
if ($mergeTranslations) {
$this->translations = array_merge($this->translations, $translations);
} else {
$this->translations = $translations;
}
return true;
}
protected function init() {
......@@ -118,35 +128,27 @@ class OC_L10N implements \OCP\IL10N {
if(array_key_exists($app.'::'.$lang, self::$cache)) {
$this->translations = self::$cache[$app.'::'.$lang]['t'];
} else{
$i18ndir = self::findI18nDir($app);
$i18nDir = self::findI18nDir($app);
$transFile = strip_tags($i18nDir).strip_tags($lang).'.json';
// Texts are in $i18ndir
// (Just no need to define date/time format etc. twice)
if((OC_Helper::isSubDirectory($i18ndir.$lang.'.php', OC::$SERVERROOT.'/core/l10n/')
|| OC_Helper::isSubDirectory($i18ndir.$lang.'.php', OC::$SERVERROOT.'/lib/l10n/')
|| OC_Helper::isSubDirectory($i18ndir.$lang.'.php', OC::$SERVERROOT.'/settings')
|| OC_Helper::isSubDirectory($i18ndir.$lang.'.php', OC_App::getAppPath($app).'/l10n/')
if((OC_Helper::isSubDirectory($transFile, OC::$SERVERROOT.'/core/l10n/')
|| OC_Helper::isSubDirectory($transFile, OC::$SERVERROOT.'/lib/l10n/')
|| OC_Helper::isSubDirectory($transFile, OC::$SERVERROOT.'/settings')
|| OC_Helper::isSubDirectory($transFile, OC_App::getAppPath($app).'/l10n/')
)
&& file_exists($i18ndir.$lang.'.php')) {
// Include the file, save the data from $CONFIG
$transFile = strip_tags($i18ndir).strip_tags($lang).'.php';
include $transFile;
if(isset($TRANSLATIONS) && is_array($TRANSLATIONS)) {
$this->translations = $TRANSLATIONS;
&& file_exists($transFile)) {
// load the translations file
if($this->load($transFile)) {
//merge with translations from theme
$theme = OC_Config::getValue( "theme" );
if (!is_null($theme)) {
$transFile = OC::$SERVERROOT.'/themes/'.$theme.substr($transFile, strlen(OC::$SERVERROOT));
if (file_exists($transFile)) {
include $transFile;
if (isset($TRANSLATIONS) && is_array($TRANSLATIONS)) {
$this->translations = array_merge($this->translations, $TRANSLATIONS);
}
$this->load($transFile, true);
}
}
}
if(isset($PLURAL_FORMS)) {
$this->plural_form_string = $PLURAL_FORMS;
}
}
self::$cache[$app.'::'.$lang]['t'] = $this->translations;
......@@ -273,10 +275,10 @@ class OC_L10N implements \OCP\IL10N {
*/
public function getPluralFormFunction() {
$this->init();
if(is_null($this->plural_form_function)) {
$this->plural_form_function = $this->createPluralFormFunction($this->plural_form_string);
if(is_null($this->pluralFormFunction)) {
$this->pluralFormFunction = $this->createPluralFormFunction($this->pluralFormString);
}
return $this->plural_form_function;
return $this->pluralFormFunction;
}
/**
......@@ -479,8 +481,8 @@ class OC_L10N implements \OCP\IL10N {
if(is_dir($dir)) {
$files=scandir($dir);
foreach($files as $file) {
if(substr($file, -4, 4) === '.php' && substr($file, 0, 4) !== 'l10n') {
$i = substr($file, 0, -4);
if(substr($file, -5, 5) === '.json' && substr($file, 0, 4) !== 'l10n') {
$i = substr($file, 0, -5);
$available[] = $i;
}
}
......
{
"translations" : {
"_%n window_::_%n windows_" : ["%n okno", "%n okna", "%n oken"]
},
"pluralForm" : "nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;"
}
<?php
$TRANSLATIONS = array(
"_%n window_::_%n windows_" => array("%n okno", "%n okna", "%n oken")
);
$PLURAL_FORMS = "nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;";
{
"translations" : {
"_%n file_::_%n files_": ["%n Datei", "%n Dateien"]
},
"pluralForm" : "nplurals=2; plural=(n != 1);"
}
<?php
$TRANSLATIONS = array(
"_%n file_::_%n files_" => array("%n Datei", "%n Dateien")
);
$PLURAL_FORMS = "nplurals=2; plural=(n != 1);";
{
"translations" : {
"_%n file_::_%n files_" : ["%n файл", "%n файла", "%n файлов"]
},
"pluralForm" : "nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);"
}
<?php
$TRANSLATIONS = array(
"_%n file_::_%n files_" => array("%n файл", "%n файла", "%n файлов")
);
$PLURAL_FORMS = "nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);";
......@@ -10,7 +10,7 @@ class Test_L10n extends PHPUnit_Framework_TestCase {
public function testGermanPluralTranslations() {
$l = new OC_L10N('test');
$transFile = OC::$SERVERROOT.'/tests/data/l10n/de.php';
$transFile = OC::$SERVERROOT.'/tests/data/l10n/de.json';
$l->load($transFile);
$this->assertEquals('1 Datei', (string)$l->n('%n file', '%n files', 1));
......@@ -19,7 +19,7 @@ class Test_L10n extends PHPUnit_Framework_TestCase {
public function testRussianPluralTranslations() {
$l = new OC_L10N('test');
$transFile = OC::$SERVERROOT.'/tests/data/l10n/ru.php';
$transFile = OC::$SERVERROOT.'/tests/data/l10n/ru.json';
$l->load($transFile);
$this->assertEquals('1 файл', (string)$l->n('%n file', '%n files', 1));
......@@ -44,7 +44,7 @@ class Test_L10n extends PHPUnit_Framework_TestCase {
public function testCzechPluralTranslations() {
$l = new OC_L10N('test');
$transFile = OC::$SERVERROOT.'/tests/data/l10n/cs.php';
$transFile = OC::$SERVERROOT.'/tests/data/l10n/cs.json';
$l->load($transFile);
$this->assertEquals('1 okno', (string)$l->n('%n window', '%n windows', 1));
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment