GithubHelp home page GithubHelp logo

phpmyadmin / motranslator Goto Github PK

View Code? Open in Web Editor NEW
53.0 10.0 26.0 711 KB

Translation API for PHP using Gettext MO files

Home Page: https://packagist.org/packages/phpmyadmin/motranslator

License: GNU General Public License v2.0

PHP 99.93% Modelica 0.07%
gettext mo-files php-gettext php plural-equations

motranslator's Introduction

phpMyAdmin

A web interface for MySQL and MariaDB.

https://www.phpmyadmin.net/

Code status

Testsuite End-to-End tests Documentation build status Translation status Coverage percentage Code quality score CII Best Practices Type coverage Infection MSI

Download

You can get the newest release at https://www.phpmyadmin.net/.

If you prefer to follow the Git repository, the following branch and tag names may be of interest:

  • STABLE is the current stable release.
  • master is the development branch.
  • Releases are tagged; for example, version 5.0.1 was tagged as RELEASE_5_0_1.

Note that phpMyAdmin uses Composer to manage library dependencies; when using Git development versions, you must manually run Composer. Please see the documentation for details.

More Information

Please see https://docs.phpmyadmin.net/, or browse the documentation in the docs folder.

For support or security issues, you can visit https://www.phpmyadmin.net/

Translations are welcome. You can translate phpMyAdmin into your language.

If you would like to contribute to the phpMyAdmin's codebase, you can read the code contribution file or browse our website's contributing page.

motranslator's People

Contributors

aschuch247 avatar carusogabriel avatar chipco avatar gnutix avatar ibennetch avatar igor-imvu avatar kamil-tekiela avatar kynx avatar madhuracj avatar mauriciofauth avatar nijel avatar powerkiki avatar remicollet avatar williamdes avatar zhb avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

motranslator's Issues

Change $cache_translations to protected or add method setCachedTranslations(array)

Hi!

I am trying to implement in-memory cache for motranslator, but I noticed I have to loop the whole array and call setTranslation() for each msgid. Maybe you could simplify it by changing cache_translations to protected or by adding another method for setting all translations at once?

class CachedTranslator extends Translator
{
	/**
	 * @param string $filename
	 */
	public function __construct($filename)
	{
		// TODO: read from cache, set $cached_translations and return or let it continue with reading the file on cache miss.
		parent::__construct($filename);
	}
}

Thank you!

add stripping of disallowed chars in sanitizePluralExpression

consider adding:

$expr = preg_replace('@[^n0-9:\(\)\?=!<>/%&|]@', '', $expr); 

as was happened before: a3ceb85#diff-cd35f60a79ff75867f0d5cbd2e9fbcf2L175
to restrict which chars can be passed to symfony/expression-language which allow usage of constant function to retrieve constant data, and regex usage via matches (both may be used together to leak constant data)
https://symfony.com/doc/current/components/expression_language/syntax.html

>= usage instead of > in read function

in read function:

if ($pos + $bytes >= $this->_len) {
            throw new ReaderException('Not enough bytes!');
        }

>= should be replaced by > (there will be enough bytes if $pos + $bytes equal to $this->_len)

PHP Notice in extractPluralCount function

Run:

include 'vendor/autoload.php';
$loader = new PhpMyAdmin\MoTranslator\Translator('test.mo');
$loader->extractPluralCount('nplurals');

result:

PHP Notice:  Undefined offset: 1 in .../vendor/phpmyadmin/motranslator/src/Translator.php on line 200

Dummy _bind_textdomain_codeset implementation

The implementation of _bind_textdomain_codeset is:

/**
 * Dummy compatibility function, MoTranslator assumes
 * everything is UTF-8
 *
 * @return void
 */
function _bind_textdomain_codeset($domain, $codeset) {
    return;
}

in documentation (under Limitations):

Input and output encoding has to match (preferably UTF-8)

fix:
1. change the documentation (if non UTF-8 isn't supported) or change comment before _bind_textdomain_codeset function (assume input & output encoding are the same)
2. throw exception (NotImplemented) in _bind_textdomain_codeset function if:

		strtolower($codeset) !== 'utf-8'

as the code will do nothing instead of changing codeset.

Number format may be changed inadvertently

At \PhpMyAdmin\MoTranslator\Loader::setlocale() we can find this:

        $this->locale = $locale;
        // Set system locales as well
        if (function_exists('setlocale')) {
            setlocale(0, $locale);
        }

In my Windows box with the official PHP/5.6.21 binaries (php-5.6.21-Win32-VC11-x86) the LC_... constant that has zero as value is LC_ALL. This basically breaks all code that assumes that numbers gets serialised in locale-independent way, e.g.:

/* @var SimpleXMLElement $xml */
/* @var float $amount */
$xml->addChild('amount', $amount); // Implicit cast to string produces: <amount>3,14</amount>

setlocale() should be called with constants rather than plain integers.

Helper script and sample output:

<?php
echo php_uname(), PHP_EOL;
echo PHP_VERSION, PHP_EOL;
$constants = get_defined_constants(true);
asort($constants['standard']);
foreach ($constants['standard'] as $name => $value) {
	if (mb_substr($name, 0, 3) === 'LC_') {
		printf('% -11s = %s', $name, $value); echo PHP_EOL;
	}
}
Windows NT SOFT2121B 6.2 build 9200 (Unknow Windows version Business Edition) i586
5.3.28
LC_ALL      = 0
LC_COLLATE  = 1
LC_CTYPE    = 2
LC_MONETARY = 3
LC_NUMERIC  = 4
LC_TIME     = 5

Linux SOFT2121b 4.4.0-43-Microsoft #1-Microsoft Wed Dec 31 14:42:53 PST 2014 x86_64
5.5.9-1ubuntu4.21
LC_CTYPE    = 0
LC_NUMERIC  = 1
LC_TIME     = 2
LC_COLLATE  = 3
LC_MONETARY = 4
LC_MESSAGES = 5
LC_ALL      = 6

PHP Fatal error: Uncaught Symfony\Component\ExpressionLanguage\SyntaxError

There missing catching of exception caused by incorrect input to Symfony evaluate method, example:
Run:

<?php
include 'vendor/autoload.php';
$t=new PhpMyAdmin\MoTranslator\Translator('2.mo');
print_r($t);
print_r($t->ngettext(chr(90).chr(4).chr(88),chr(67).chr(0).chr(68),8));

Result:

PHP Fatal error:  Uncaught Symfony\Component\ExpressionLanguage\SyntaxError: Unclosed "(" around position 0 for expression `(n*2`. in /vendor/symfony/expression-language/Lexer.php:98

2.mo file was generated by nodejs script:

var gettextParser = require("gettext-parser");
d = {
  "headers": {
    "plural-forms": "nplurals=20; plural=(n*2;"
  },
 
  "translations": {
    "Z": {
      "X": {
        "msgid_plural": "C\x00D",
      }
    }
  }
}

var output = gettextParser.mo.compile(d);
var fs = require('fs');
fs.writeFile("2.mo", output, function(err) {
    if(err) {
        return console.log(err);
    }

    console.log("The file was saved!");
});

PHP Notice in getPluralForms function

Run:

<?php
$negative32 = pack('CCCC', 0xFF, 0xFF, 0xFF, 0xFF);
$total = pack('V',8);
$dummy = pack('V',2);
$originals = pack('V',1); // total
$translations = pack('V',4);
file_put_contents('fpd1.mo',"\xde\x12\x04\x95".$total.$originals.$translations.$translations.'dddddddddd');

include 'vendor/autoload.php';
$t=new PhpMyAdmin\MoTranslator\Translator('fpd1.mo');
print_r($t);
print_r($t->ngettext(chr(18).chr(4).chr(149).chr(8),chr(0).chr(0).chr(1),1));
?>

Result:

PHP Notice:  Undefined index:  in /vendor/phpmyadmin/motranslator/src/Translator.php on line 235

Remove use of eval()

For gettext we need something what is able to evaluate it's plural expressions and not use eval() (see phpmyadmin/phpmyadmin#6363), unfortunately I was not able to find single arithmetic expression evaluation library for PHP which supports ternary operator, but they tend to support dozen of other stuff we don't need like functions. Therefore I think it will be better to implement own code for this particular use case. The final goal is to remove eval usage.

Example expression we need to evaluate for any arbitrary value of n: n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=11 ? 4 : 5

The syntax is quite limited:

  • n variable
  • ternary operator ? :
  • comparisons == < > <= => !=
  • division and modulo / %
  • numbers

PS: More plural examples can be found in the Localization Guide.

Include twig support

Can you add the following files (from phpMyAdmin) to provide twig support:

  • Twig\I18nExtension
  • Twig\I18n\TokenParserTrans
  • Twig\I18n\NodeTrans

In my local test this works perfectly (using my namespace)

$twig->addExtension(new PhpMyAdmin\Twig\I18nExtension());

on the readme.md Gettext compatability usage add these

I might be a good thing to add these under the Gettext compatibility usage so people know they have been replicated.

// Other Functions
_dnpgettext($domain, $msgctxt, $msgid, $msgidPlural, $number)
_dngettext($domain, $msgid, $msgidPlural, $number)
_npgettext($msgctxt, $msgid, $msgidPlural, $number)
_ngettext($msgid, $msgidPlural, $number)
_dpgettext($domain, $msgctxt, $msgid)
_dgettext($domain, $msgid)
_pgettext($msgctxt, $msgid)

fpd on 32bit via negative result of unpack

unpack function on PHP that run in 32bit mode can return negative result as noted by the documentation: https://secure.php.net/manual/en/function.unpack.php#refsect1-function.unpack-notes

Note that PHP internally stores integral values as signed. If you unpack a large unsigned long and it is of the same size as PHP internally stored values the result will be a negative number even though unsigned unpacking was specified.

thus can result in PHP Warning.
example: (run under PHP 32bit)

<?php
$negative32 = pack('CCCC', 0xFF, 0xFF, 0xFF, 0xFF);
file_put_contents('fpdle.mo',"\xde\x12\x04\x95".str_repeat($negative32,6));

include 'vendor/autoload.php';
$t=new PhpMyAdmin\MoTranslator\Translator('fpdle.mo');
print_r($t);
?>

result:

PHP Warning:  unpack(): Type V: not enough input, need 4, have 0 in /vendor/phpmyadmin/motranslator/src/StringReader.php on line 88
PHP Warning:  unpack(): Type V: not enough input, need 4, have 0 in /vendor/phpmyadmin/motranslator/src/StringReader.php on line 88

PHP Notice in ngettext function

in https://github.com/phpmyadmin/motranslator/blob/master/src/Translator.php#L290:

        return $list[$select];

Run:

<?php
include 'vendor/autoload.php';
$t=new PhpMyAdmin\MoTranslator\Translator('2.mo');
print_r($t);
print_r($t->ngettext(chr(90).chr(4).chr(88),chr(67).chr(0).chr(68),8));
?>

Result:

PHP Notice:  Undefined offset: 16 in /vendor/phpmyadmin/motranslator/src/Translator.php on line 290

2.mo file was generated by nodejs script:

var gettextParser = require("gettext-parser");

d = {
  "headers": {
    "plural-forms": "nplurals=20; plural=(n*2);"
  },
 
  "translations": {
    "Z": {
      "X": {
        "msgid_plural": "C\x00D",
      }
    }
  }
}

var output = gettextParser.mo.compile(d);
var fs = require('fs');
fs.writeFile("2.mo", output, function(err) {
    if(err) {
        return console.log(err);
    }

    console.log("The file was saved!");
});

trim usage when ltrim/rtrim can be used instead

  1. extractPluralCount function in:
if (strtolower(trim($nplurals[0])) != 'nplurals') {

trim can be replaced with rtrim (because previous call to trim on $parts[0] get rid of spaces from beginning of the string)

  1. sanitizePluralExpression function in
$expr = trim(substr($expr, 6));
$expr = trim(substr($expr, 1));

trim can be replaced by ltrim (because previous call to trim on strtolower($expr) get rid of spaces from end of the string)

Tests fail on i386

https://salsa.debian.org/phpmyadmin-team/motranslator/-/jobs/1168052#L1509

1) PhpMyAdmin\MoTranslator\Tests\MoFilesTest::testEmptyMoFile with data set #4 ('./tests/data/error/fpdle.mo')
TypeError: Argument 3 passed to PhpMyAdmin\MoTranslator\StringReader::readintarray() must be of the type int,
 float given, called in src/Translator.php on line 140

$tableOriginals = $stream->readintarray($unpack, $originals, $total * 2);

return unpack($unpack . $count, $this->read($pos, 4 * $count));

int $number parameter marked as string

The selectString function receive $n as int

param int $n count of objects

while the $number parameter in ngettext & npgettext functions are marked as string

param string $number Number of objects

while it's passed to selectString function.

fix:
change description of $number to int.

Bad usage of global functions.

Cannot redeclare __() (previously declared in /var/www/site/vendor/laravel/framework/src/Illuminate/Foundation/helpers.php:967

This package does not work with Laravel, and possible others because of the usage of global functions.

It would be great if you would wrap all the global functions in an if (!function_exists()) call to ensure this does not happen.

Possible incorrect dependencies: PHP/5.3.0 does not seem to be supported

I suspect that motranslator requirements don't consider dependencies properly:

"require": {
    "php": ">=5.3.0",
    "symfony/expression-language": "^4.0 || ^3.2 || ^2.8"
},

โ€ฆ but oldest supported expression-language requirements say:

"require": {
    "php": ">=5.3.9"
},

So there's no way to install with Composer under PHP versions earlier than 5.3.9.

(expression-language bumped PHP version from 5.3.3 to 5.3.9 in v2.7.0-BETA1, not idea why.)

Switching locale during one process run

Hi there,

I have and issue where I need to be able to switch locale for the domain during the same process run. Reading through the code, I found that Loader instance is memoizing Translator instances into domains variable under only domain key. So when I switch to another locale, it does not instantiate new Translator instance for the same domain.

Does it make sense to add locale to the keys for Translators. Either as sub-array or change the keys to have both domain and locale as one key (e.g messages_en_US) ?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.