first commit

This commit is contained in:
Ryan Ariana
2024-05-06 11:04:37 +07:00
commit aee061ddba
7322 changed files with 2918816 additions and 0 deletions

View File

@@ -0,0 +1,25 @@
<?php
// autoload.php @generated by Composer
if (PHP_VERSION_ID < 50600) {
if (!headers_sent()) {
header('HTTP/1.1 500 Internal Server Error');
}
$err = 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
if (!ini_get('display_errors')) {
if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') {
fwrite(STDERR, $err);
} elseif (!headers_sent()) {
echo $err;
}
}
trigger_error(
$err,
E_USER_ERROR
);
}
require_once __DIR__ . '/composer/autoload_real.php';
return ComposerAutoloaderInitf9c47eb45bab6a60bddbc2200bbbe7e7::getLoader();

View File

@@ -0,0 +1,579 @@
<?php
/*
* This file is part of Composer.
*
* (c) Nils Adermann <naderman@naderman.de>
* Jordi Boggiano <j.boggiano@seld.be>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Composer\Autoload;
/**
* ClassLoader implements a PSR-0, PSR-4 and classmap class loader.
*
* $loader = new \Composer\Autoload\ClassLoader();
*
* // register classes with namespaces
* $loader->add('Symfony\Component', __DIR__.'/component');
* $loader->add('Symfony', __DIR__.'/framework');
*
* // activate the autoloader
* $loader->register();
*
* // to enable searching the include path (eg. for PEAR packages)
* $loader->setUseIncludePath(true);
*
* In this example, if you try to use a class in the Symfony\Component
* namespace or one of its children (Symfony\Component\Console for instance),
* the autoloader will first look for the class under the component/
* directory, and it will then fallback to the framework/ directory if not
* found before giving up.
*
* This class is loosely based on the Symfony UniversalClassLoader.
*
* @author Fabien Potencier <fabien@symfony.com>
* @author Jordi Boggiano <j.boggiano@seld.be>
* @see https://www.php-fig.org/psr/psr-0/
* @see https://www.php-fig.org/psr/psr-4/
*/
class ClassLoader
{
/** @var \Closure(string):void */
private static $includeFile;
/** @var string|null */
private $vendorDir;
// PSR-4
/**
* @var array<string, array<string, int>>
*/
private $prefixLengthsPsr4 = array();
/**
* @var array<string, list<string>>
*/
private $prefixDirsPsr4 = array();
/**
* @var list<string>
*/
private $fallbackDirsPsr4 = array();
// PSR-0
/**
* List of PSR-0 prefixes
*
* Structured as array('F (first letter)' => array('Foo\Bar (full prefix)' => array('path', 'path2')))
*
* @var array<string, array<string, list<string>>>
*/
private $prefixesPsr0 = array();
/**
* @var list<string>
*/
private $fallbackDirsPsr0 = array();
/** @var bool */
private $useIncludePath = false;
/**
* @var array<string, string>
*/
private $classMap = array();
/** @var bool */
private $classMapAuthoritative = false;
/**
* @var array<string, bool>
*/
private $missingClasses = array();
/** @var string|null */
private $apcuPrefix;
/**
* @var array<string, self>
*/
private static $registeredLoaders = array();
/**
* @param string|null $vendorDir
*/
public function __construct($vendorDir = null)
{
$this->vendorDir = $vendorDir;
self::initializeIncludeClosure();
}
/**
* @return array<string, list<string>>
*/
public function getPrefixes()
{
if (!empty($this->prefixesPsr0)) {
return call_user_func_array('array_merge', array_values($this->prefixesPsr0));
}
return array();
}
/**
* @return array<string, list<string>>
*/
public function getPrefixesPsr4()
{
return $this->prefixDirsPsr4;
}
/**
* @return list<string>
*/
public function getFallbackDirs()
{
return $this->fallbackDirsPsr0;
}
/**
* @return list<string>
*/
public function getFallbackDirsPsr4()
{
return $this->fallbackDirsPsr4;
}
/**
* @return array<string, string> Array of classname => path
*/
public function getClassMap()
{
return $this->classMap;
}
/**
* @param array<string, string> $classMap Class to filename map
*
* @return void
*/
public function addClassMap(array $classMap)
{
if ($this->classMap) {
$this->classMap = array_merge($this->classMap, $classMap);
} else {
$this->classMap = $classMap;
}
}
/**
* Registers a set of PSR-0 directories for a given prefix, either
* appending or prepending to the ones previously set for this prefix.
*
* @param string $prefix The prefix
* @param list<string>|string $paths The PSR-0 root directories
* @param bool $prepend Whether to prepend the directories
*
* @return void
*/
public function add($prefix, $paths, $prepend = false)
{
$paths = (array) $paths;
if (!$prefix) {
if ($prepend) {
$this->fallbackDirsPsr0 = array_merge(
$paths,
$this->fallbackDirsPsr0
);
} else {
$this->fallbackDirsPsr0 = array_merge(
$this->fallbackDirsPsr0,
$paths
);
}
return;
}
$first = $prefix[0];
if (!isset($this->prefixesPsr0[$first][$prefix])) {
$this->prefixesPsr0[$first][$prefix] = $paths;
return;
}
if ($prepend) {
$this->prefixesPsr0[$first][$prefix] = array_merge(
$paths,
$this->prefixesPsr0[$first][$prefix]
);
} else {
$this->prefixesPsr0[$first][$prefix] = array_merge(
$this->prefixesPsr0[$first][$prefix],
$paths
);
}
}
/**
* Registers a set of PSR-4 directories for a given namespace, either
* appending or prepending to the ones previously set for this namespace.
*
* @param string $prefix The prefix/namespace, with trailing '\\'
* @param list<string>|string $paths The PSR-4 base directories
* @param bool $prepend Whether to prepend the directories
*
* @throws \InvalidArgumentException
*
* @return void
*/
public function addPsr4($prefix, $paths, $prepend = false)
{
$paths = (array) $paths;
if (!$prefix) {
// Register directories for the root namespace.
if ($prepend) {
$this->fallbackDirsPsr4 = array_merge(
$paths,
$this->fallbackDirsPsr4
);
} else {
$this->fallbackDirsPsr4 = array_merge(
$this->fallbackDirsPsr4,
$paths
);
}
} elseif (!isset($this->prefixDirsPsr4[$prefix])) {
// Register directories for a new namespace.
$length = strlen($prefix);
if ('\\' !== $prefix[$length - 1]) {
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
}
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
$this->prefixDirsPsr4[$prefix] = $paths;
} elseif ($prepend) {
// Prepend directories for an already registered namespace.
$this->prefixDirsPsr4[$prefix] = array_merge(
$paths,
$this->prefixDirsPsr4[$prefix]
);
} else {
// Append directories for an already registered namespace.
$this->prefixDirsPsr4[$prefix] = array_merge(
$this->prefixDirsPsr4[$prefix],
$paths
);
}
}
/**
* Registers a set of PSR-0 directories for a given prefix,
* replacing any others previously set for this prefix.
*
* @param string $prefix The prefix
* @param list<string>|string $paths The PSR-0 base directories
*
* @return void
*/
public function set($prefix, $paths)
{
if (!$prefix) {
$this->fallbackDirsPsr0 = (array) $paths;
} else {
$this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
}
}
/**
* Registers a set of PSR-4 directories for a given namespace,
* replacing any others previously set for this namespace.
*
* @param string $prefix The prefix/namespace, with trailing '\\'
* @param list<string>|string $paths The PSR-4 base directories
*
* @throws \InvalidArgumentException
*
* @return void
*/
public function setPsr4($prefix, $paths)
{
if (!$prefix) {
$this->fallbackDirsPsr4 = (array) $paths;
} else {
$length = strlen($prefix);
if ('\\' !== $prefix[$length - 1]) {
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
}
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
$this->prefixDirsPsr4[$prefix] = (array) $paths;
}
}
/**
* Turns on searching the include path for class files.
*
* @param bool $useIncludePath
*
* @return void
*/
public function setUseIncludePath($useIncludePath)
{
$this->useIncludePath = $useIncludePath;
}
/**
* Can be used to check if the autoloader uses the include path to check
* for classes.
*
* @return bool
*/
public function getUseIncludePath()
{
return $this->useIncludePath;
}
/**
* Turns off searching the prefix and fallback directories for classes
* that have not been registered with the class map.
*
* @param bool $classMapAuthoritative
*
* @return void
*/
public function setClassMapAuthoritative($classMapAuthoritative)
{
$this->classMapAuthoritative = $classMapAuthoritative;
}
/**
* Should class lookup fail if not found in the current class map?
*
* @return bool
*/
public function isClassMapAuthoritative()
{
return $this->classMapAuthoritative;
}
/**
* APCu prefix to use to cache found/not-found classes, if the extension is enabled.
*
* @param string|null $apcuPrefix
*
* @return void
*/
public function setApcuPrefix($apcuPrefix)
{
$this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null;
}
/**
* The APCu prefix in use, or null if APCu caching is not enabled.
*
* @return string|null
*/
public function getApcuPrefix()
{
return $this->apcuPrefix;
}
/**
* Registers this instance as an autoloader.
*
* @param bool $prepend Whether to prepend the autoloader or not
*
* @return void
*/
public function register($prepend = false)
{
spl_autoload_register(array($this, 'loadClass'), true, $prepend);
if (null === $this->vendorDir) {
return;
}
if ($prepend) {
self::$registeredLoaders = array($this->vendorDir => $this) + self::$registeredLoaders;
} else {
unset(self::$registeredLoaders[$this->vendorDir]);
self::$registeredLoaders[$this->vendorDir] = $this;
}
}
/**
* Unregisters this instance as an autoloader.
*
* @return void
*/
public function unregister()
{
spl_autoload_unregister(array($this, 'loadClass'));
if (null !== $this->vendorDir) {
unset(self::$registeredLoaders[$this->vendorDir]);
}
}
/**
* Loads the given class or interface.
*
* @param string $class The name of the class
* @return true|null True if loaded, null otherwise
*/
public function loadClass($class)
{
if ($file = $this->findFile($class)) {
$includeFile = self::$includeFile;
$includeFile($file);
return true;
}
return null;
}
/**
* Finds the path to the file where the class is defined.
*
* @param string $class The name of the class
*
* @return string|false The path if found, false otherwise
*/
public function findFile($class)
{
// class map lookup
if (isset($this->classMap[$class])) {
return $this->classMap[$class];
}
if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
return false;
}
if (null !== $this->apcuPrefix) {
$file = apcu_fetch($this->apcuPrefix.$class, $hit);
if ($hit) {
return $file;
}
}
$file = $this->findFileWithExtension($class, '.php');
// Search for Hack files if we are running on HHVM
if (false === $file && defined('HHVM_VERSION')) {
$file = $this->findFileWithExtension($class, '.hh');
}
if (null !== $this->apcuPrefix) {
apcu_add($this->apcuPrefix.$class, $file);
}
if (false === $file) {
// Remember that this class does not exist.
$this->missingClasses[$class] = true;
}
return $file;
}
/**
* Returns the currently registered loaders keyed by their corresponding vendor directories.
*
* @return array<string, self>
*/
public static function getRegisteredLoaders()
{
return self::$registeredLoaders;
}
/**
* @param string $class
* @param string $ext
* @return string|false
*/
private function findFileWithExtension($class, $ext)
{
// PSR-4 lookup
$logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
$first = $class[0];
if (isset($this->prefixLengthsPsr4[$first])) {
$subPath = $class;
while (false !== $lastPos = strrpos($subPath, '\\')) {
$subPath = substr($subPath, 0, $lastPos);
$search = $subPath . '\\';
if (isset($this->prefixDirsPsr4[$search])) {
$pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);
foreach ($this->prefixDirsPsr4[$search] as $dir) {
if (file_exists($file = $dir . $pathEnd)) {
return $file;
}
}
}
}
}
// PSR-4 fallback dirs
foreach ($this->fallbackDirsPsr4 as $dir) {
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
return $file;
}
}
// PSR-0 lookup
if (false !== $pos = strrpos($class, '\\')) {
// namespaced class name
$logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
. strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
} else {
// PEAR-like class name
$logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
}
if (isset($this->prefixesPsr0[$first])) {
foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
if (0 === strpos($class, $prefix)) {
foreach ($dirs as $dir) {
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
return $file;
}
}
}
}
}
// PSR-0 fallback dirs
foreach ($this->fallbackDirsPsr0 as $dir) {
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
return $file;
}
}
// PSR-0 include paths.
if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
return $file;
}
return false;
}
/**
* @return void
*/
private static function initializeIncludeClosure()
{
if (self::$includeFile !== null) {
return;
}
/**
* Scope isolated include.
*
* Prevents access to $this/self from included files.
*
* @param string $file
* @return void
*/
self::$includeFile = \Closure::bind(static function($file) {
include $file;
}, null, null);
}
}

View File

@@ -0,0 +1,359 @@
<?php
/*
* This file is part of Composer.
*
* (c) Nils Adermann <naderman@naderman.de>
* Jordi Boggiano <j.boggiano@seld.be>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Composer;
use Composer\Autoload\ClassLoader;
use Composer\Semver\VersionParser;
/**
* This class is copied in every Composer installed project and available to all
*
* See also https://getcomposer.org/doc/07-runtime.md#installed-versions
*
* To require its presence, you can require `composer-runtime-api ^2.0`
*
* @final
*/
class InstalledVersions
{
/**
* @var mixed[]|null
* @psalm-var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}|array{}|null
*/
private static $installed;
/**
* @var bool|null
*/
private static $canGetVendors;
/**
* @var array[]
* @psalm-var array<string, array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
*/
private static $installedByVendor = array();
/**
* Returns a list of all package names which are present, either by being installed, replaced or provided
*
* @return string[]
* @psalm-return list<string>
*/
public static function getInstalledPackages()
{
$packages = array();
foreach (self::getInstalled() as $installed) {
$packages[] = array_keys($installed['versions']);
}
if (1 === \count($packages)) {
return $packages[0];
}
return array_keys(array_flip(\call_user_func_array('array_merge', $packages)));
}
/**
* Returns a list of all package names with a specific type e.g. 'library'
*
* @param string $type
* @return string[]
* @psalm-return list<string>
*/
public static function getInstalledPackagesByType($type)
{
$packagesByType = array();
foreach (self::getInstalled() as $installed) {
foreach ($installed['versions'] as $name => $package) {
if (isset($package['type']) && $package['type'] === $type) {
$packagesByType[] = $name;
}
}
}
return $packagesByType;
}
/**
* Checks whether the given package is installed
*
* This also returns true if the package name is provided or replaced by another package
*
* @param string $packageName
* @param bool $includeDevRequirements
* @return bool
*/
public static function isInstalled($packageName, $includeDevRequirements = true)
{
foreach (self::getInstalled() as $installed) {
if (isset($installed['versions'][$packageName])) {
return $includeDevRequirements || !isset($installed['versions'][$packageName]['dev_requirement']) || $installed['versions'][$packageName]['dev_requirement'] === false;
}
}
return false;
}
/**
* Checks whether the given package satisfies a version constraint
*
* e.g. If you want to know whether version 2.3+ of package foo/bar is installed, you would call:
*
* Composer\InstalledVersions::satisfies(new VersionParser, 'foo/bar', '^2.3')
*
* @param VersionParser $parser Install composer/semver to have access to this class and functionality
* @param string $packageName
* @param string|null $constraint A version constraint to check for, if you pass one you have to make sure composer/semver is required by your package
* @return bool
*/
public static function satisfies(VersionParser $parser, $packageName, $constraint)
{
$constraint = $parser->parseConstraints((string) $constraint);
$provided = $parser->parseConstraints(self::getVersionRanges($packageName));
return $provided->matches($constraint);
}
/**
* Returns a version constraint representing all the range(s) which are installed for a given package
*
* It is easier to use this via isInstalled() with the $constraint argument if you need to check
* whether a given version of a package is installed, and not just whether it exists
*
* @param string $packageName
* @return string Version constraint usable with composer/semver
*/
public static function getVersionRanges($packageName)
{
foreach (self::getInstalled() as $installed) {
if (!isset($installed['versions'][$packageName])) {
continue;
}
$ranges = array();
if (isset($installed['versions'][$packageName]['pretty_version'])) {
$ranges[] = $installed['versions'][$packageName]['pretty_version'];
}
if (array_key_exists('aliases', $installed['versions'][$packageName])) {
$ranges = array_merge($ranges, $installed['versions'][$packageName]['aliases']);
}
if (array_key_exists('replaced', $installed['versions'][$packageName])) {
$ranges = array_merge($ranges, $installed['versions'][$packageName]['replaced']);
}
if (array_key_exists('provided', $installed['versions'][$packageName])) {
$ranges = array_merge($ranges, $installed['versions'][$packageName]['provided']);
}
return implode(' || ', $ranges);
}
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
}
/**
* @param string $packageName
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present
*/
public static function getVersion($packageName)
{
foreach (self::getInstalled() as $installed) {
if (!isset($installed['versions'][$packageName])) {
continue;
}
if (!isset($installed['versions'][$packageName]['version'])) {
return null;
}
return $installed['versions'][$packageName]['version'];
}
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
}
/**
* @param string $packageName
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present
*/
public static function getPrettyVersion($packageName)
{
foreach (self::getInstalled() as $installed) {
if (!isset($installed['versions'][$packageName])) {
continue;
}
if (!isset($installed['versions'][$packageName]['pretty_version'])) {
return null;
}
return $installed['versions'][$packageName]['pretty_version'];
}
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
}
/**
* @param string $packageName
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as reference
*/
public static function getReference($packageName)
{
foreach (self::getInstalled() as $installed) {
if (!isset($installed['versions'][$packageName])) {
continue;
}
if (!isset($installed['versions'][$packageName]['reference'])) {
return null;
}
return $installed['versions'][$packageName]['reference'];
}
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
}
/**
* @param string $packageName
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as install path. Packages of type metapackages also have a null install path.
*/
public static function getInstallPath($packageName)
{
foreach (self::getInstalled() as $installed) {
if (!isset($installed['versions'][$packageName])) {
continue;
}
return isset($installed['versions'][$packageName]['install_path']) ? $installed['versions'][$packageName]['install_path'] : null;
}
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
}
/**
* @return array
* @psalm-return array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}
*/
public static function getRootPackage()
{
$installed = self::getInstalled();
return $installed[0]['root'];
}
/**
* Returns the raw installed.php data for custom implementations
*
* @deprecated Use getAllRawData() instead which returns all datasets for all autoloaders present in the process. getRawData only returns the first dataset loaded, which may not be what you expect.
* @return array[]
* @psalm-return array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}
*/
public static function getRawData()
{
@trigger_error('getRawData only returns the first dataset loaded, which may not be what you expect. Use getAllRawData() instead which returns all datasets for all autoloaders present in the process.', E_USER_DEPRECATED);
if (null === self::$installed) {
// only require the installed.php file if this file is loaded from its dumped location,
// and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
if (substr(__DIR__, -8, 1) !== 'C') {
self::$installed = include __DIR__ . '/installed.php';
} else {
self::$installed = array();
}
}
return self::$installed;
}
/**
* Returns the raw data of all installed.php which are currently loaded for custom implementations
*
* @return array[]
* @psalm-return list<array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
*/
public static function getAllRawData()
{
return self::getInstalled();
}
/**
* Lets you reload the static array from another file
*
* This is only useful for complex integrations in which a project needs to use
* this class but then also needs to execute another project's autoloader in process,
* and wants to ensure both projects have access to their version of installed.php.
*
* A typical case would be PHPUnit, where it would need to make sure it reads all
* the data it needs from this class, then call reload() with
* `require $CWD/vendor/composer/installed.php` (or similar) as input to make sure
* the project in which it runs can then also use this class safely, without
* interference between PHPUnit's dependencies and the project's dependencies.
*
* @param array[] $data A vendor/composer/installed.php data set
* @return void
*
* @psalm-param array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $data
*/
public static function reload($data)
{
self::$installed = $data;
self::$installedByVendor = array();
}
/**
* @return array[]
* @psalm-return list<array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
*/
private static function getInstalled()
{
if (null === self::$canGetVendors) {
self::$canGetVendors = method_exists('Composer\Autoload\ClassLoader', 'getRegisteredLoaders');
}
$installed = array();
if (self::$canGetVendors) {
foreach (ClassLoader::getRegisteredLoaders() as $vendorDir => $loader) {
if (isset(self::$installedByVendor[$vendorDir])) {
$installed[] = self::$installedByVendor[$vendorDir];
} elseif (is_file($vendorDir.'/composer/installed.php')) {
/** @var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $required */
$required = require $vendorDir.'/composer/installed.php';
$installed[] = self::$installedByVendor[$vendorDir] = $required;
if (null === self::$installed && strtr($vendorDir.'/composer', '\\', '/') === strtr(__DIR__, '\\', '/')) {
self::$installed = $installed[count($installed) - 1];
}
}
}
}
if (null === self::$installed) {
// only require the installed.php file if this file is loaded from its dumped location,
// and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
if (substr(__DIR__, -8, 1) !== 'C') {
/** @var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $required */
$required = require __DIR__ . '/installed.php';
self::$installed = $required;
} else {
self::$installed = array();
}
}
if (self::$installed !== array()) {
$installed[] = self::$installed;
}
return $installed;
}
}

View File

@@ -0,0 +1,21 @@
Copyright (c) Nils Adermann, Jordi Boggiano
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@@ -0,0 +1,11 @@
<?php
// autoload_classmap.php @generated by Composer
$vendorDir = dirname(__DIR__);
$baseDir = dirname($vendorDir);
return array(
'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php',
'Weglot\\TranslationDefinitions' => $vendorDir . '/weglot/translation-definitions/index.php',
);

View File

@@ -0,0 +1,10 @@
<?php
// autoload_files.php @generated by Composer
$vendorDir = dirname(__DIR__);
$baseDir = dirname($vendorDir);
return array(
'6c200413eed8aeea54dbaf934a31b127' => $vendorDir . '/weglot/simplehtmldom/src/simple_html_dom.php',
);

View File

@@ -0,0 +1,10 @@
<?php
// autoload_namespaces.php @generated by Composer
$vendorDir = dirname(__DIR__);
$baseDir = dirname($vendorDir);
return array(
'WGSimpleHtmlDom' => array($vendorDir . '/weglot/simplehtmldom/src'),
);

View File

@@ -0,0 +1,13 @@
<?php
// autoload_psr4.php @generated by Composer
$vendorDir = dirname(__DIR__);
$baseDir = dirname($vendorDir);
return array(
'Weglot\\' => array($vendorDir . '/weglot/weglot-php/src'),
'Psr\\Cache\\' => array($vendorDir . '/psr/cache/src'),
'Morphism\\' => array($vendorDir . '/gmulti/morphism-php/lib'),
'Languages\\' => array($vendorDir . '/weglot/weglot-php/node_modules/@weglot/languages/dist'),
);

View File

@@ -0,0 +1,50 @@
<?php
// autoload_real.php @generated by Composer
class ComposerAutoloaderInitf9c47eb45bab6a60bddbc2200bbbe7e7
{
private static $loader;
public static function loadClassLoader($class)
{
if ('Composer\Autoload\ClassLoader' === $class) {
require __DIR__ . '/ClassLoader.php';
}
}
/**
* @return \Composer\Autoload\ClassLoader
*/
public static function getLoader()
{
if (null !== self::$loader) {
return self::$loader;
}
require __DIR__ . '/platform_check.php';
spl_autoload_register(array('ComposerAutoloaderInitf9c47eb45bab6a60bddbc2200bbbe7e7', 'loadClassLoader'), true, true);
self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__));
spl_autoload_unregister(array('ComposerAutoloaderInitf9c47eb45bab6a60bddbc2200bbbe7e7', 'loadClassLoader'));
require __DIR__ . '/autoload_static.php';
call_user_func(\Composer\Autoload\ComposerStaticInitf9c47eb45bab6a60bddbc2200bbbe7e7::getInitializer($loader));
$loader->register(true);
$filesToLoad = \Composer\Autoload\ComposerStaticInitf9c47eb45bab6a60bddbc2200bbbe7e7::$files;
$requireFile = \Closure::bind(static function ($fileIdentifier, $file) {
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
$GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
require $file;
}
}, null, null);
foreach ($filesToLoad as $fileIdentifier => $file) {
$requireFile($fileIdentifier, $file);
}
return $loader;
}
}

View File

@@ -0,0 +1,76 @@
<?php
// autoload_static.php @generated by Composer
namespace Composer\Autoload;
class ComposerStaticInitf9c47eb45bab6a60bddbc2200bbbe7e7
{
public static $files = array (
'6c200413eed8aeea54dbaf934a31b127' => __DIR__ . '/..' . '/weglot/simplehtmldom/src/simple_html_dom.php',
);
public static $prefixLengthsPsr4 = array (
'W' =>
array (
'Weglot\\' => 7,
),
'P' =>
array (
'Psr\\Cache\\' => 10,
),
'M' =>
array (
'Morphism\\' => 9,
),
'L' =>
array (
'Languages\\' => 10,
),
);
public static $prefixDirsPsr4 = array (
'Weglot\\' =>
array (
0 => __DIR__ . '/..' . '/weglot/weglot-php/src',
),
'Psr\\Cache\\' =>
array (
0 => __DIR__ . '/..' . '/psr/cache/src',
),
'Morphism\\' =>
array (
0 => __DIR__ . '/..' . '/gmulti/morphism-php/lib',
),
'Languages\\' =>
array (
0 => __DIR__ . '/..' . '/weglot/weglot-php/node_modules/@weglot/languages/dist',
),
);
public static $prefixesPsr0 = array (
'W' =>
array (
'WGSimpleHtmlDom' =>
array (
0 => __DIR__ . '/..' . '/weglot/simplehtmldom/src',
),
),
);
public static $classMap = array (
'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php',
'Weglot\\TranslationDefinitions' => __DIR__ . '/..' . '/weglot/translation-definitions/index.php',
);
public static function getInitializer(ClassLoader $loader)
{
return \Closure::bind(function () use ($loader) {
$loader->prefixLengthsPsr4 = ComposerStaticInitf9c47eb45bab6a60bddbc2200bbbe7e7::$prefixLengthsPsr4;
$loader->prefixDirsPsr4 = ComposerStaticInitf9c47eb45bab6a60bddbc2200bbbe7e7::$prefixDirsPsr4;
$loader->prefixesPsr0 = ComposerStaticInitf9c47eb45bab6a60bddbc2200bbbe7e7::$prefixesPsr0;
$loader->classMap = ComposerStaticInitf9c47eb45bab6a60bddbc2200bbbe7e7::$classMap;
}, null, ClassLoader::class);
}
}

View File

@@ -0,0 +1,267 @@
{
"packages": [
{
"name": "gmulti/morphism-php",
"version": "dev-dev-bugfix",
"version_normalized": "dev-dev-bugfix",
"source": {
"type": "git",
"url": "https://github.com/glx77/morphism-php.git",
"reference": "578752d5a21b57dd6e6cf4c04f12c96c3df42372"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/glx77/morphism-php/zipball/578752d5a21b57dd6e6cf4c04f12c96c3df42372",
"reference": "578752d5a21b57dd6e6cf4c04f12c96c3df42372",
"shasum": ""
},
"require-dev": {
"phpunit/phpunit": "^6.5"
},
"time": "2023-10-09T06:46:30+00:00",
"type": "project",
"installation-source": "dist",
"autoload": {
"psr-4": {
"Morphism\\": "lib/"
}
},
"license": [
"MIT"
],
"authors": [
{
"name": "Thomas DENEULIN",
"email": "thomas@delipress.io"
}
],
"support": {
"source": "https://github.com/glx77/morphism-php/tree/dev-bugfix"
},
"install-path": "../gmulti/morphism-php"
},
{
"name": "psr/cache",
"version": "1.0.1",
"version_normalized": "1.0.1.0",
"source": {
"type": "git",
"url": "https://github.com/php-fig/cache.git",
"reference": "d11b50ad223250cf17b86e38383413f5a6764bf8"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/cache/zipball/d11b50ad223250cf17b86e38383413f5a6764bf8",
"reference": "d11b50ad223250cf17b86e38383413f5a6764bf8",
"shasum": ""
},
"require": {
"php": ">=5.3.0"
},
"time": "2016-08-06T20:24:11+00:00",
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"installation-source": "dist",
"autoload": {
"psr-4": {
"Psr\\Cache\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "PHP-FIG",
"homepage": "http://www.php-fig.org/"
}
],
"description": "Common interface for caching libraries",
"keywords": [
"cache",
"psr",
"psr-6"
],
"support": {
"source": "https://github.com/php-fig/cache/tree/master"
},
"install-path": "../psr/cache"
},
{
"name": "weglot/simplehtmldom",
"version": "0.8",
"version_normalized": "0.8.0.0",
"source": {
"type": "git",
"url": "git@github.com:weglot/simple_html_dom.git",
"reference": "bc37c23550025c59849f0f0e8c332d6e7c2385ee"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/weglot/simple_html_dom/zipball/bc37c23550025c59849f0f0e8c332d6e7c2385ee",
"reference": "bc37c23550025c59849f0f0e8c332d6e7c2385ee",
"shasum": ""
},
"require": {
"php": ">=5.3.0"
},
"time": "2023-03-28T08:51:53+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
"psr-0": {
"WGSimpleHtmlDom": "src/"
},
"files": [
"src/simple_html_dom.php"
]
},
"license": [
"MIT"
],
"authors": [
{
"name": "S.C. Chen",
"email": "me578022@gmail.com"
}
],
"description": "Composer package that gives you access to and (unlike all the others at this time) autoloads S.C. Chen's PHP Simple HTML DOM Parser Library",
"homepage": "http://simplehtmldom.sourceforge.net/",
"keywords": [
"dom",
"html",
"simple"
],
"support": {
"source": "https://github.com/weglot/simple_html_dom/tree/0.8"
},
"install-path": "../weglot/simplehtmldom"
},
{
"name": "weglot/translation-definitions",
"version": "v2.3.4",
"version_normalized": "2.3.4.0",
"source": {
"type": "git",
"url": "https://github.com/weglot/weglot-translation-definitions.git",
"reference": "f54b91a863e529f3efbc0c68acde7731a57176de"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/weglot/weglot-translation-definitions/zipball/f54b91a863e529f3efbc0c68acde7731a57176de",
"reference": "f54b91a863e529f3efbc0c68acde7731a57176de",
"shasum": ""
},
"require": {
"php": ">=5"
},
"time": "2021-02-18T14:47:45+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
"classmap": [
"index.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Mehdi Rejraji",
"email": "mehdi@weglot.com"
}
],
"description": "Weglot's shared definitions",
"support": {
"issues": "https://github.com/weglot/weglot-translation-definitions/issues",
"source": "https://github.com/weglot/weglot-translation-definitions/tree/v2.3.4"
},
"install-path": "../weglot/translation-definitions"
},
{
"name": "weglot/weglot-php",
"version": "1.7.1",
"version_normalized": "1.7.1.0",
"source": {
"type": "git",
"url": "git@github.com:weglot/weglot-php.git",
"reference": "c99f9094a087220ba711aefc743fc7d0f8f9eee1"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/weglot/weglot-php/zipball/c99f9094a087220ba711aefc743fc7d0f8f9eee1",
"reference": "c99f9094a087220ba711aefc743fc7d0f8f9eee1",
"shasum": ""
},
"require": {
"php": ">=5.6",
"psr/cache": "^1.0",
"weglot/simplehtmldom": "^0.8",
"weglot/translation-definitions": "^2.0"
},
"require-dev": {
"phpstan/phpstan-deprecation-rules": "^1.1",
"vlucas/phpdotenv": "^2.4"
},
"time": "2024-01-18T12:41:47+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
"psr-4": {
"Weglot\\": "src/",
"Languages\\": "node_modules/@weglot/languages/dist/"
}
},
"license": [
"MIT"
],
"authors": [
{
"name": "Baptiste Leduc",
"email": "baptiste@weglot.com",
"homepage": "https://baptiste-leduc.now.sh/",
"role": "Developer"
},
{
"name": "Thomas Deneulin",
"email": "thomas@weglot.com",
"role": "Review"
},
{
"name": "Edson Galina Fortes",
"email": "edson@weglot.com",
"role": "Developer"
}
],
"description": "PHP library for the Weglot API",
"homepage": "https://weglot.com/",
"keywords": [
"i18n",
"languages",
"localization",
"php",
"translate",
"translation",
"translator",
"weglot",
"weglot-library"
],
"support": {
"email": "support@weglot.com",
"source": "https://github.com/weglot/weglot-php",
"docs": "https://weglot.github.io/weglot-documentation/",
"issues": "https://github.com/weglot/weglot-php/issues"
},
"install-path": "../weglot/weglot-php"
}
],
"dev": false,
"dev-package-names": []
}

View File

@@ -0,0 +1,68 @@
<?php return array(
'root' => array(
'name' => 'weglot/translate-wordpress',
'pretty_version' => 'dev-master',
'version' => 'dev-master',
'reference' => '56d55e0185af2c410d9ba415990e82a3f6041cd4',
'type' => 'project',
'install_path' => __DIR__ . '/../../',
'aliases' => array(),
'dev' => false,
),
'versions' => array(
'gmulti/morphism-php' => array(
'pretty_version' => 'dev-dev-bugfix',
'version' => 'dev-dev-bugfix',
'reference' => '578752d5a21b57dd6e6cf4c04f12c96c3df42372',
'type' => 'project',
'install_path' => __DIR__ . '/../gmulti/morphism-php',
'aliases' => array(),
'dev_requirement' => false,
),
'psr/cache' => array(
'pretty_version' => '1.0.1',
'version' => '1.0.1.0',
'reference' => 'd11b50ad223250cf17b86e38383413f5a6764bf8',
'type' => 'library',
'install_path' => __DIR__ . '/../psr/cache',
'aliases' => array(),
'dev_requirement' => false,
),
'weglot/simplehtmldom' => array(
'pretty_version' => '0.8',
'version' => '0.8.0.0',
'reference' => 'bc37c23550025c59849f0f0e8c332d6e7c2385ee',
'type' => 'library',
'install_path' => __DIR__ . '/../weglot/simplehtmldom',
'aliases' => array(),
'dev_requirement' => false,
),
'weglot/translate-wordpress' => array(
'pretty_version' => 'dev-master',
'version' => 'dev-master',
'reference' => '56d55e0185af2c410d9ba415990e82a3f6041cd4',
'type' => 'project',
'install_path' => __DIR__ . '/../../',
'aliases' => array(),
'dev_requirement' => false,
),
'weglot/translation-definitions' => array(
'pretty_version' => 'v2.3.4',
'version' => '2.3.4.0',
'reference' => 'f54b91a863e529f3efbc0c68acde7731a57176de',
'type' => 'library',
'install_path' => __DIR__ . '/../weglot/translation-definitions',
'aliases' => array(),
'dev_requirement' => false,
),
'weglot/weglot-php' => array(
'pretty_version' => '1.7.1',
'version' => '1.7.1.0',
'reference' => 'c99f9094a087220ba711aefc743fc7d0f8f9eee1',
'type' => 'library',
'install_path' => __DIR__ . '/../weglot/weglot-php',
'aliases' => array(),
'dev_requirement' => false,
),
),
);

View File

@@ -0,0 +1,26 @@
<?php
// platform_check.php @generated by Composer
$issues = array();
if (!(PHP_VERSION_ID >= 50600)) {
$issues[] = 'Your Composer dependencies require a PHP version ">= 5.6.0". You are running ' . PHP_VERSION . '.';
}
if ($issues) {
if (!headers_sent()) {
header('HTTP/1.1 500 Internal Server Error');
}
if (!ini_get('display_errors')) {
if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') {
fwrite(STDERR, 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . implode(PHP_EOL, $issues) . PHP_EOL.PHP_EOL);
} elseif (!headers_sent()) {
echo 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . str_replace('You are running '.PHP_VERSION.'.', '', implode(PHP_EOL, $issues)) . PHP_EOL.PHP_EOL;
}
}
trigger_error(
'Composer detected issues in your platform: ' . implode(' ', $issues),
E_USER_ERROR
);
}

View File

@@ -0,0 +1,14 @@
branches:
only:
- master
- develop
before_script:
- composer dump
language: php
php:
- '5.6'
- '7.0'
- '7.1'
- nightly

View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2017 Thomas Deneulin
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -0,0 +1,238 @@
# Morphism PHP
[![Build Status][travis-image]][travis-url]
> Helps you to transform any object structure to another.
This library is inspired by Yann Renaudin's : [Morphism library](https://github.com/emyann/morphism)
## Contribution
- Twitter: [@TDeneulin][twitter-account]
- Pull requests and stars are always welcome 🙏🏽 For bugs and feature requests, [please create an issue](https://github.com/Gmulti/morphism-php/issues)
## Getting started 🚀
Install `morphism-php` using composer : `composer require gmulti/morphism-php`.
```php
use Morphism\Morphism;
```
## What does it do? 🤔
Morphism uses a semantic configuration to go through the collection of graph objects you have to process. Then it extracts and computes the value from the specified path(s). Finally, it sets this value to the destination property from the schema.
## Usage 🍔
Morphism is curried function that allows a partial application with a semantic configuration. You can use it in many ways:
### Example
```php
// Target type you want to have
class User {
public function __construct($firstName, $lastName, $phoneNumber){
$this->firstName = $firstName;
$this->lastName = $lastName;
$this->phoneNumber = $phoneNumber;
       $this->city = null;
  }
}
// Data source you want to map
$data = array(
"name" => "Iron Man",
"firstName" => "Tony",
"lastName" => "Stark",
"address" => array(
"city" => "New York City",
"country" => "USA"
),
"phoneNumber" => array(
array(
"type" => "home",
"number" => "212 555-1234"
),
array(
"type" => "mobile",
"number" => "646 555-4567"
)
)
);
// Mapping Schema ( see more examples below )
$schema = array(
"city" => "address.city",
"name" => function($data){
return strtoupper($data["name"]);
}
);
Morphism::setMapper("User", $schema);
// Map using the registered type and the registry
$result = Morphism::map("User", $data);
/// *** OUTPUT *** ///
class User {
public $city // string(13) "New York City"
public $name // string(8) "iron man"
}
```
### Multidimensional array
```php
// Target type you want to have
class User {
}
// Data source you want to map
$data = array(
array(
"name" => "Iron Man",
"firstName" => "Tony",
"lastName" => "Stark",
"address" => array(
"city" => "New York City",
"country" => "USA"
),
"phoneNumber" => array(
array(
"type" => "home",
"number" => "212 555-1234"
),
array(
"type" => "mobile",
"number" => "646 555-4567"
)
)
),
array(
"name" => "Spiderman",
"firstName" => "Peter",
"lastName" => "Parker",
"address" => array(
"city" => "New York City",
"country" => "USA"
),
"phoneNumber" => array(
array(
"type" => "home",
"number" => "999 999-9999"
)
)
)
);
// Mapping Schema ( see more examples below )
$schema = array(
"city" => "address.city",
"name" => function($data){
return strtoupper($data["name"]);
}
);
Morphism::setMapper("User", $schema);
// Map using the registered type and the registry
$result = Morphism::map("User", $data);
/// *** OUTPUT *** ///
array(
class User {
public $city // string(13) "New York City"
public $name // string(8) "iron man"
},
class User {
public $city // string(13) "New York City"
public $name // string(8) "spiderman"
}
)
```
## Schema Examples
### Dataset sample
```php
$data = array(
"name" => "Iron Man",
"firstName" => "Tony",
"lastName" => "Stark",
"address" => array(
"city" => "New York City",
"country" => "USA"
),
"phoneNumber" => array(
array(
"type" => "home",
"number" => "212 555-1234"
),
array(
"type" => "mobile",
"number" => "646 555-4567"
)
)
);
// Target type you want to have
class User {
}
```
### Agregator
```php
// Schema
$schema = array(
"fullName" => array("firstName", "lastName")
);
Morphism::setMapper("User", $schema);
// Map using the registered type and the registry
$result = Morphism::map("User", $data);
/// *** OUTPUT *** ///
class User {
public $fullName // "Tony Stark"
}
```
### Computing over Flattening / Projection
```php
// Schema
$schema = array(
"city" => (object) array(
"path" => "address.city",
"fn" => function($city) {
return strtolower($city);
}
),
"nbContacts" => function($data){
return count($data["phoneNumber"]);
}
);
Morphism::setMapper("User", $schema);
// Map using the registered type and the registry
$result = Morphism::map("User", $data);
/// *** OUTPUT *** ///
class User {
public $city // "new york city" <= strtolower
public $nbContacts // 2 <= computed from the object
}
```
## License
MIT © [Thomas Deneulin][twitter-account]
[twitter-account]: https://twitter.com/TDeneulin
[travis-image]: https://travis-ci.org/Gmulti/morphism-php.svg?branch=master
[travis-url]: https://travis-ci.org/Gmulti/morphism-php

View File

@@ -0,0 +1,20 @@
{
"name": "gmulti/morphism-php",
"type": "project",
"license": "MIT",
"authors": [
{
"name": "Thomas DENEULIN",
"email": "thomas@delipress.io"
}
],
"minimum-stability": "stable",
"autoload": {
"psr-4": {
"Morphism\\": "lib/"
}
},
"require-dev": {
"phpunit/phpunit": "^6.5"
}
}

View File

@@ -0,0 +1,91 @@
<?php
namespace Morphism\Helpers;
#[AllowDynamicProperties]
trait MorphismHelper {
/**
* Source : https://stackoverflow.com/questions/5458241/php-dynamic-array-index-name
*
* @static
* @param array $array
* @param array $indexes
*/
protected static function getArrayValue(array $array, array $indexes)
{
if (count($array) == 0 || count($indexes) == 0) {
return false;
}
$index = array_shift($indexes);
if(!array_key_exists($index, $array)){
return false;
}
$value = $array[$index];
if (count($indexes) == 0) {
return $value;
}
if(!is_array($value)) {
return false;
}
return self::getArrayValue($value, $indexes);
}
/**
* @static
* @param array $paths
* @param array $object
* @return string
*/
protected static function agregator($paths, $object){
return array_reduce($paths, function($delta, $path) use ($object) {
$searchPath = $path;
if(!is_array($path)){
$searchPath = array($path);
}
return trim(sprintf("%s %s", $delta, self::getArrayValue($object, $searchPath) ));
});
}
/**
* @static
* @param array $object
* @param array $schema
* @param array $data
* @return object
*/
protected static function transformValuesFromObject($object, $schema, $data){
foreach($schema as $key => $target){ // iterate on every action of the schema
if(is_string($target)){ // Target<String>: string path => [ target: 'source' ]
$indexes = explode(".", $target);
$object->{$key} = self::getArrayValue($data, $indexes);
}
else if(is_callable($target)){
$object->{$key} = call_user_func($target, $data);
}
else if (is_array($target)){
$object->{$key} = self::agregator($target, $data);
}
else if(is_object($target) ) {
$searchPath = $target->path;
if(is_array($target->path)){
$value = self::agregator($target->path, $data);
}
else{
$indexes = explode(".", $target->path);
$value = self::getArrayValue($data, $indexes);
}
$object->{$key} = call_user_func($target->fn, $value);
}
}
return $object;
}
}

View File

@@ -0,0 +1,86 @@
<?php
namespace Morphism;
use Morphism\Helpers\MorphismHelper;
#[AllowDynamicProperties]
abstract class Morphism {
use MorphismHelper;
protected static $registries = array();
public static function register($type, $schema) {
}
/**
* @static
* @param string $type
* @return bool
*/
public static function exists($type){
return array_key_exists($type, self::$registries);
}
/**
* @static
* @param string $type
* @return array
*/
public static function getMapper($type){
return self::$registries[$type];
}
/**
* @static
* @param string $type
* @param array $schema
*/
public static function setMapper($type, $schema){
if (!$type) {
throw new \Exception('type paramater is required when register a mapping');
}
if (!$schema) {
throw new \Exception('schema paramater is required when register a mapping');
}
self::$registries[$type] = $schema;
}
/**
* @static
* @param string $type
*/
public static function deleteMapper($type){
unset(self::$registries[$type]);
}
/**
* @static
* @param string $type
* @param array $data
*/
public static function map($type, $data){
if(!Morphism::exists($type)){
throw new \Exception(sprintf("Mapper for %s not exist", $type));
}
$reflectedClass = new \ReflectionClass($type);
if(!$reflectedClass->isInstantiable()){
throw new \Exception($type . " is not an instantiable class.");
}
if(isset($data[0])){
return array_map(function($arr) use($reflectedClass, $type){
$instance = $reflectedClass->newInstance();
return self::transformValuesFromObject($instance, Morphism::getMapper($type), $arr);
}, $data);
}
else{
$instance = $reflectedClass->newInstance();
return self::transformValuesFromObject($instance, Morphism::getMapper($type), $data);
}
}
}

View File

@@ -0,0 +1,7 @@
<phpunit bootstrap="vendor/autoload.php" colors="true">
<testsuites>
<testsuite name="Morphism">
<directory>tests</directory>
</testsuite>
</testsuites>
</phpunit>

View File

@@ -0,0 +1,5 @@
<?php
class User {
}

View File

@@ -0,0 +1,112 @@
<?php
use PHPUnit\Framework\TestCase;
use Morphism\Morphism;
class MorphismArrayTest extends TestCase
{
public function setUp(){
$this->data = array(
array(
"name" => "Iron Man",
"firstName" => "Tony",
"lastName" => "Stark",
"address" => array(
"city" => "New York City",
"country" => "USA"
),
"phoneNumber" => array(
array(
"type" => "home",
"number" => "212 555-1234"
),
array(
"type" => "mobile",
"number" => "646 555-4567"
)
)
),
array(
"name" => "Spiderman",
"firstName" => "Peter",
"lastName" => "Parker",
"address" => array(
"city" => "New York City",
"country" => "USA"
),
"phoneNumber" => array(
array(
"type" => "home",
"number" => "293 093-2321"
)
)
)
);
}
public function testActionArrayStringPath()
{
$schema = array(
"city" => "address.city"
);
Morphism::setMapper("User", $schema);
$result = Morphism::map("User", $this->data);
$this->assertEquals(count($result), 2);
$this->assertEquals($result[0]->city, "New York City");
}
public function testActionFunctionPath(){
$schema = array(
"city" => function($data){
return strtolower($data["address"]["city"]);
}
);
Morphism::setMapper("User", $schema);
$result = Morphism::map("User", $this->data);
$this->assertEquals($result[0]->city, "new york city");
$this->assertEquals($result[1]->city, "new york city");
}
public function testActionAgregatorPath(){
$schema = array(
"fullName" => array(
"firstName", "lastName"
)
);
Morphism::setMapper("User", $schema);
$result = Morphism::map("User", $this->data);
$this->assertEquals($result[0]->fullName, "Tony Stark");
$this->assertEquals($result[1]->fullName, "Peter Parker");
}
public function testActionFunctionObjectPath(){
$schema = array(
"city" => (object) array(
"path" => "address.city",
"fn" => function($city) {
return strtolower($city);
}
)
);
Morphism::setMapper("User", $schema);
$result = Morphism::map("User", $this->data);
$this->assertEquals($result[0]->city, "new york city");
$this->assertEquals($result[1]->city, "new york city");
}
}

View File

@@ -0,0 +1,91 @@
<?php
use PHPUnit\Framework\TestCase;
use Morphism\Morphism;
require __DIR__ . "/Mocks/User.php";
class MorphismTest extends TestCase
{
public function setUp(){
$this->data = array(
"name" => "Iron Man",
"firstName" => "Tony",
"lastName" => "Stark",
"address" => array(
"city" => "New York City",
"country" => "USA"
),
"phoneNumber" => array(
array(
"type" => "home",
"number" => "212 555-1234"
),
array(
"type" => "mobile",
"number" => "646 555-4567"
)
)
);
}
public function testActionStringPath(){
$schema = array(
"city" => "address.city"
);
Morphism::setMapper("User", $schema);
$result = Morphism::map("User", $this->data);
$this->assertEquals($result->city, "New York City");
}
public function testActionFunctionPath(){
$schema = array(
"city" => function($data){
return strtolower($data["address"]["city"]);
}
);
Morphism::setMapper("User", $schema);
$result = Morphism::map("User", $this->data);
$this->assertEquals($result->city, "new york city");
}
public function testActionAgregatorPath(){
$schema = array(
"fullName" => array(
"firstName", "lastName"
)
);
Morphism::setMapper("User", $schema);
$result = Morphism::map("User", $this->data);
$this->assertEquals($result->fullName, "Tony Stark");
}
public function testActionFunctionObjectPath(){
$schema = array(
"city" => (object) array(
"path" => "address.city",
"fn" => function($city) {
return strtolower($city);
}
)
);
Morphism::setMapper("User", $schema);
$result = Morphism::map("User", $this->data);
$this->assertEquals($result->city, "new york city");
}
}

View File

@@ -0,0 +1,16 @@
# Changelog
All notable changes to this project will be documented in this file, in reverse chronological order by release.
## 1.0.1 - 2016-08-06
### Fixed
- Make spacing consistent in phpdoc annotations php-fig/cache#9 - chalasr
- Fix grammar in phpdoc annotations php-fig/cache#10 - chalasr
- Be more specific in docblocks that `getItems()` and `deleteItems()` take an array of strings (`string[]`) compared to just `array` php-fig/cache#8 - GrahamCampbell
- For `expiresAt()` and `expiresAfter()` in CacheItemInterface fix docblock to specify null as a valid parameters as well as an implementation of DateTimeInterface php-fig/cache#7 - GrahamCampbell
## 1.0.0 - 2015-12-11
Initial stable release; reflects accepted PSR-6 specification

View File

@@ -0,0 +1,19 @@
Copyright (c) 2015 PHP Framework Interoperability Group
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@@ -0,0 +1,9 @@
PSR Cache
=========
This repository holds all interfaces defined by
[PSR-6](http://www.php-fig.org/psr/psr-6/).
Note that this is not a Cache implementation of its own. It is merely an
interface that describes a Cache implementation. See the specification for more
details.

View File

@@ -0,0 +1,25 @@
{
"name": "psr/cache",
"description": "Common interface for caching libraries",
"keywords": ["psr", "psr-6", "cache"],
"license": "MIT",
"authors": [
{
"name": "PHP-FIG",
"homepage": "http://www.php-fig.org/"
}
],
"require": {
"php": ">=5.3.0"
},
"autoload": {
"psr-4": {
"Psr\\Cache\\": "src/"
}
},
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
}
}

View File

@@ -0,0 +1,10 @@
<?php
namespace Psr\Cache;
/**
* Exception interface for all exceptions thrown by an Implementing Library.
*/
interface CacheException
{
}

View File

@@ -0,0 +1,105 @@
<?php
namespace Psr\Cache;
/**
* CacheItemInterface defines an interface for interacting with objects inside a cache.
*
* Each Item object MUST be associated with a specific key, which can be set
* according to the implementing system and is typically passed by the
* Cache\CacheItemPoolInterface object.
*
* The Cache\CacheItemInterface object encapsulates the storage and retrieval of
* cache items. Each Cache\CacheItemInterface is generated by a
* Cache\CacheItemPoolInterface object, which is responsible for any required
* setup as well as associating the object with a unique Key.
* Cache\CacheItemInterface objects MUST be able to store and retrieve any type
* of PHP value defined in the Data section of the specification.
*
* Calling Libraries MUST NOT instantiate Item objects themselves. They may only
* be requested from a Pool object via the getItem() method. Calling Libraries
* SHOULD NOT assume that an Item created by one Implementing Library is
* compatible with a Pool from another Implementing Library.
*/
interface CacheItemInterface
{
/**
* Returns the key for the current cache item.
*
* The key is loaded by the Implementing Library, but should be available to
* the higher level callers when needed.
*
* @return string
* The key string for this cache item.
*/
public function getKey();
/**
* Retrieves the value of the item from the cache associated with this object's key.
*
* The value returned must be identical to the value originally stored by set().
*
* If isHit() returns false, this method MUST return null. Note that null
* is a legitimate cached value, so the isHit() method SHOULD be used to
* differentiate between "null value was found" and "no value was found."
*
* @return mixed
* The value corresponding to this cache item's key, or null if not found.
*/
public function get();
/**
* Confirms if the cache item lookup resulted in a cache hit.
*
* Note: This method MUST NOT have a race condition between calling isHit()
* and calling get().
*
* @return bool
* True if the request resulted in a cache hit. False otherwise.
*/
public function isHit();
/**
* Sets the value represented by this cache item.
*
* The $value argument may be any item that can be serialized by PHP,
* although the method of serialization is left up to the Implementing
* Library.
*
* @param mixed $value
* The serializable value to be stored.
*
* @return static
* The invoked object.
*/
public function set($value);
/**
* Sets the expiration time for this cache item.
*
* @param \DateTimeInterface|null $expiration
* The point in time after which the item MUST be considered expired.
* If null is passed explicitly, a default value MAY be used. If none is set,
* the value should be stored permanently or for as long as the
* implementation allows.
*
* @return static
* The called object.
*/
public function expiresAt($expiration);
/**
* Sets the expiration time for this cache item.
*
* @param int|\DateInterval|null $time
* The period of time from the present after which the item MUST be considered
* expired. An integer parameter is understood to be the time in seconds until
* expiration. If null is passed explicitly, a default value MAY be used.
* If none is set, the value should be stored permanently or for as long as the
* implementation allows.
*
* @return static
* The called object.
*/
public function expiresAfter($time);
}

View File

@@ -0,0 +1,138 @@
<?php
namespace Psr\Cache;
/**
* CacheItemPoolInterface generates CacheItemInterface objects.
*
* The primary purpose of Cache\CacheItemPoolInterface is to accept a key from
* the Calling Library and return the associated Cache\CacheItemInterface object.
* It is also the primary point of interaction with the entire cache collection.
* All configuration and initialization of the Pool is left up to an
* Implementing Library.
*/
interface CacheItemPoolInterface
{
/**
* Returns a Cache Item representing the specified key.
*
* This method must always return a CacheItemInterface object, even in case of
* a cache miss. It MUST NOT return null.
*
* @param string $key
* The key for which to return the corresponding Cache Item.
*
* @throws InvalidArgumentException
* If the $key string is not a legal value a \Psr\Cache\InvalidArgumentException
* MUST be thrown.
*
* @return CacheItemInterface
* The corresponding Cache Item.
*/
public function getItem($key);
/**
* Returns a traversable set of cache items.
*
* @param string[] $keys
* An indexed array of keys of items to retrieve.
*
* @throws InvalidArgumentException
* If any of the keys in $keys are not a legal value a \Psr\Cache\InvalidArgumentException
* MUST be thrown.
*
* @return array|\Traversable
* A traversable collection of Cache Items keyed by the cache keys of
* each item. A Cache item will be returned for each key, even if that
* key is not found. However, if no keys are specified then an empty
* traversable MUST be returned instead.
*/
public function getItems(array $keys = array());
/**
* Confirms if the cache contains specified cache item.
*
* Note: This method MAY avoid retrieving the cached value for performance reasons.
* This could result in a race condition with CacheItemInterface::get(). To avoid
* such situation use CacheItemInterface::isHit() instead.
*
* @param string $key
* The key for which to check existence.
*
* @throws InvalidArgumentException
* If the $key string is not a legal value a \Psr\Cache\InvalidArgumentException
* MUST be thrown.
*
* @return bool
* True if item exists in the cache, false otherwise.
*/
public function hasItem($key);
/**
* Deletes all items in the pool.
*
* @return bool
* True if the pool was successfully cleared. False if there was an error.
*/
public function clear();
/**
* Removes the item from the pool.
*
* @param string $key
* The key to delete.
*
* @throws InvalidArgumentException
* If the $key string is not a legal value a \Psr\Cache\InvalidArgumentException
* MUST be thrown.
*
* @return bool
* True if the item was successfully removed. False if there was an error.
*/
public function deleteItem($key);
/**
* Removes multiple items from the pool.
*
* @param string[] $keys
* An array of keys that should be removed from the pool.
* @throws InvalidArgumentException
* If any of the keys in $keys are not a legal value a \Psr\Cache\InvalidArgumentException
* MUST be thrown.
*
* @return bool
* True if the items were successfully removed. False if there was an error.
*/
public function deleteItems(array $keys);
/**
* Persists a cache item immediately.
*
* @param CacheItemInterface $item
* The cache item to save.
*
* @return bool
* True if the item was successfully persisted. False if there was an error.
*/
public function save(CacheItemInterface $item);
/**
* Sets a cache item to be persisted later.
*
* @param CacheItemInterface $item
* The cache item to save.
*
* @return bool
* False if the item could not be queued or if a commit was attempted and failed. True otherwise.
*/
public function saveDeferred(CacheItemInterface $item);
/**
* Persists any deferred cache items.
*
* @return bool
* True if all not-yet-saved items were successfully saved or there were none. False otherwise.
*/
public function commit();
}

View File

@@ -0,0 +1,13 @@
<?php
namespace Psr\Cache;
/**
* Exception interface for invalid cache arguments.
*
* Any time an invalid argument is passed into a method it must throw an
* exception class which implements Psr\Cache\InvalidArgumentException.
*/
interface InvalidArgumentException extends CacheException
{
}

View File

@@ -0,0 +1,31 @@
<!-- logo -->
<img src="https://cdn.weglot.com/logo/logo-hor.png" height="40" />
# simple_html_dom
[![Latest Stable Version](https://poser.pugx.org/weglot/simplehtmldom/v/stable)](https://packagist.org/packages/weglot/simplehtmldom)
[![License](https://poser.pugx.org/weglot/simplehtmldom/license)](https://packagist.org/packages/weglot/simplehtmldom)
## Overview
Simple fork of [simple_html_dom](http://simplehtmldom.sourceforge.net/) PHP library with some tweaks.
## Changelog
## [0.5] - 2019-01-03
### Changed
- Update compatibility PHP 7.3
## [0.4] - 2018-10-05
### Changed
- Change namespace for resolve conflict with other library Simple HTML DOM
## [0.3] - 2018-07-23
### Added
- redo modifications previsouly done like max size for exemple
## [0.2] - 2018-04-12
### Added
- hasAncestorAttribute function to check if a node has given attribute in his ancestors
## [0.1] - 2018-04-04
### Changed
- Weglot modifications to make `simple_html_dom` working onto WordPress

View File

@@ -0,0 +1,26 @@
{
"name": "weglot/simplehtmldom",
"description": "Composer package that gives you access to and (unlike all the others at this time) autoloads S.C. Chen's PHP Simple HTML DOM Parser Library",
"keywords": ["html", "dom", "simple"],
"homepage" : "http://simplehtmldom.sourceforge.net/",
"type": "library",
"license": "MIT",
"authors": [
{
"name": "S.C. Chen",
"email": "me578022@gmail.com"
}
],
"require": {
"php": ">=5.3.0"
},
"autoload": {
"psr-0": {
"WGSimpleHtmlDom": "src/"
},
"files": [
"src/simple_html_dom.php"
]
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2019 Weglot
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -0,0 +1,138 @@
# weglot-translation-definitions
## Project structure
- The `data` folder is meant to only contain data files (preferrably JSON)
- The root folder can contain files mean to
The project may itself contain test files and be subject to CI validation in the future, to test for the integrity of the data files.
## Javascript
### Publish a new version
You can run `yarn version` and select a new version. Alternatively, run `yarn version --{type}` where type=(major|minor|patch).
This will update both the `package.json`, create a git tag following the standard `v1.0.0` for version `1.0.0`, and push that tag to origin.
### Reference this package in other projects
Check which version you'd like to use if you don't want to use the last version (master branch). Add an entry in the dependencies:
```
{
"weglot-translation-definitions": "weglot/weglot-translation-definitions#v1.1.0"
}
```
You can also a command with the following structure:
`yarn add weglot/weglot-translation-definitions#v1.1.0`
## Routine scripts
### Update available languages
If you have HTTPie on your system, run the following command to update the list of available languages:
`http --pretty=format https://api.weglot.com/public/languages > data/available-languages.json`
You can also run `yarn update-languages`.
## PHP
### Add the dependency
In your `composer.json#repositories`, add the following entry:
```json
{
"type": "vcs",
"url": "https://github.com/weglot/weglot-translation-definitions"
}
```
In your `composer.json#require`, add the following line:
```json
"weglot/translation-definitions": "dev-master",
```
If you wish to use a specific version ([check available tags here](https://github.com/weglot/weglot-translation-definitions/tags)), just replace `master` with the tag name, like so:
```json
"weglot/translation-definitions": "dev-v1.3.2",
```
### Update the package
`composer update weglot/translation-definitions:dev-master`
### Usage
This assumes you've added the dependency through `composer.json`
```php
use Weglot\TranslationDefinitions;
print_r(TranslationDefinitions::$languages);
// Array
// (
// [0] => Array
// (
// [value] => af
// [label] => Afrikaans
// )
// [1] => Array
// (
// [value] => sq
// [label] => Albanian
// )
// etc.
print_r(TranslationDefinitions::$cases);
// Array
// (
// [v1] => Array
// (
// [0] => Array
// (
// [name] => Simple tag #1
// [body] => <p>Hello, <b>this is</b> a test!</p>
// [expected] => Array
// (
// [0] => Array
// (
// [t] => 1
// [w] => Hello,
// )
// [1] => Array
// (
// [t] => 1
// [w] => this is
// )
// etc.
print_r(TranslationDefinitions::$mergeNodesList);
// Array
// (
// [v1] => Array
// (
// )
// [v2] => Array
// (
// [0] => ABBR
// [1] => ACRONYM
// [2] => B
// [3] => BDO
// [4] => BIG
// [5] => CITE
// [6] => EM
// [7] => I
// [8] => KBD
// [9] => Q
// etc.
```

View File

@@ -0,0 +1,20 @@
{
"name": "weglot/translation-definitions",
"type": "library",
"description": "Weglot's shared definitions",
"license": "MIT",
"require": {
"php": ">=5"
},
"authors": [
{
"name": "Mehdi Rejraji",
"email": "mehdi@weglot.com"
}
],
"autoload": {
"classmap": [
"index.php"
]
}
}

View File

@@ -0,0 +1,547 @@
[
{
"code": "af",
"english_name": "Afrikaans",
"local_name": "Afrikaans"
},
{
"code": "am",
"english_name": "Amharic",
"local_name": "አማርኛ"
},
{
"code": "ar",
"english_name": "Arabic",
"local_name": "العربية‏"
},
{
"code": "az",
"english_name": "Azerbaijani",
"local_name": "Azərbaycan dili"
},
{
"code": "ba",
"english_name": "Bashkir",
"local_name": "башҡорт теле"
},
{
"code": "be",
"english_name": "Belarusian",
"local_name": "Беларуская"
},
{
"code": "bg",
"english_name": "Bulgarian",
"local_name": "Български"
},
{
"code": "bn",
"english_name": "Bengali",
"local_name": "বাংলা"
},
{
"code": "br",
"english_name": "Portuguese",
"local_name": "Português"
},
{
"code": "bs",
"english_name": "Bosnian",
"local_name": "Bosanski"
},
{
"code": "ca",
"english_name": "Catalan",
"local_name": "Català"
},
{
"code": "co",
"english_name": "Corsican",
"local_name": "Corsu"
},
{
"code": "cs",
"english_name": "Czech",
"local_name": "Čeština"
},
{
"code": "cy",
"english_name": "Welsh",
"local_name": "Cymraeg"
},
{
"code": "da",
"english_name": "Danish",
"local_name": "Dansk"
},
{
"code": "de",
"english_name": "German",
"local_name": "Deutsch"
},
{
"code": "el",
"english_name": "Greek",
"local_name": "Ελληνικά"
},
{
"code": "en",
"english_name": "English",
"local_name": "English"
},
{
"code": "eo",
"english_name": "Esperanto",
"local_name": "Esperanto"
},
{
"code": "es",
"english_name": "Spanish",
"local_name": "Español"
},
{
"code": "et",
"english_name": "Estonian",
"local_name": "Eesti"
},
{
"code": "eu",
"english_name": "Basque",
"local_name": "Euskara"
},
{
"code": "fa",
"english_name": "Persian",
"local_name": "فارسی"
},
{
"code": "fi",
"english_name": "Finnish",
"local_name": "Suomi"
},
{
"code": "fj",
"english_name": "Fijian",
"local_name": "Vosa Vakaviti"
},
{
"code": "fl",
"english_name": "Filipino",
"local_name": "Pilipino"
},
{
"code": "fr",
"english_name": "French",
"local_name": "Français"
},
{
"code": "fy",
"english_name": "Western Frisian",
"local_name": "frysk"
},
{
"code": "ga",
"english_name": "Irish",
"local_name": "Gaeilge"
},
{
"code": "gd",
"english_name": "Scottish Gaelic",
"local_name": "Gàidhlig"
},
{
"code": "gl",
"english_name": "Galician",
"local_name": "Galego"
},
{
"code": "gu",
"english_name": "Gujarati",
"local_name": "ગુજરાતી"
},
{
"code": "ha",
"english_name": "Hausa",
"local_name": "هَوُسَ"
},
{
"code": "he",
"english_name": "Hebrew",
"local_name": "עברית"
},
{
"code": "hi",
"english_name": "Hindi",
"local_name": "हिंदी"
},
{
"code": "hr",
"english_name": "Croatian",
"local_name": "Hrvatski"
},
{
"code": "ht",
"english_name": "Haitian",
"local_name": "Kreyòl ayisyen"
},
{
"code": "hu",
"english_name": "Hungarian",
"local_name": "Magyar"
},
{
"code": "hw",
"english_name": "Hawaiian",
"local_name": "Ōlelo Hawaii"
},
{
"code": "hy",
"english_name": "Armenian",
"local_name": "հայերեն"
},
{
"code": "id",
"english_name": "Indonesian",
"local_name": "Bahasa Indonesia"
},
{
"code": "ig",
"english_name": "Igbo",
"local_name": "Igbo"
},
{
"code": "is",
"english_name": "Icelandic",
"local_name": "Íslenska"
},
{
"code": "it",
"english_name": "Italian",
"local_name": "Italiano"
},
{
"code": "ja",
"english_name": "Japanese",
"local_name": "日本語"
},
{
"code": "jv",
"english_name": "Javanese",
"local_name": "Wong Jawa"
},
{
"code": "ka",
"english_name": "Georgian",
"local_name": "ქართული"
},
{
"code": "kk",
"english_name": "Kazakh",
"local_name": "Қазақша"
},
{
"code": "km",
"english_name": "Central Khmer",
"local_name": "ភាសាខ្មែរ"
},
{
"code": "kn",
"english_name": "Kannada",
"local_name": "ಕನ್ನಡ"
},
{
"code": "ko",
"english_name": "Korean",
"local_name": "한국어"
},
{
"code": "ku",
"english_name": "Kurdish",
"local_name": "كوردی"
},
{
"code": "ky",
"english_name": "Kyrgyz",
"local_name": "кыргызча"
},
{
"code": "la",
"english_name": "Latin",
"local_name": "Latine"
},
{
"code": "lb",
"english_name": "Luxembourgish",
"local_name": "Lëtzebuergesch"
},
{
"code": "lo",
"english_name": "Lao",
"local_name": "ພາສາລາວ"
},
{
"code": "lt",
"english_name": "Lithuanian",
"local_name": "Lietuvių"
},
{
"code": "lv",
"english_name": "Latvian",
"local_name": "Latviešu"
},
{
"code": "mg",
"english_name": "Malagasy",
"local_name": "Malagasy"
},
{
"code": "mi",
"english_name": "Māori",
"local_name": "te reo Māori"
},
{
"code": "mk",
"english_name": "Macedonian",
"local_name": "Македонски"
},
{
"code": "ml",
"english_name": "Malayalam",
"local_name": "മലയാളം"
},
{
"code": "mn",
"english_name": "Mongolian",
"local_name": "Монгол"
},
{
"code": "mr",
"english_name": "Marathi",
"local_name": "मराठी"
},
{
"code": "ms",
"english_name": "Malay",
"local_name": "Bahasa Melayu"
},
{
"code": "mt",
"english_name": "Maltese",
"local_name": "Malti"
},
{
"code": "my",
"english_name": "Burmese",
"local_name": "မျန္မာစာ"
},
{
"code": "ne",
"english_name": "Nepali",
"local_name": "नेपाली"
},
{
"code": "nl",
"english_name": "Dutch",
"local_name": "Nederlands"
},
{
"code": "no",
"english_name": "Norwegian",
"local_name": "Norsk"
},
{
"code": "ny",
"english_name": "Chichewa",
"local_name": "chiCheŵa"
},
{
"code": "pa",
"english_name": "Punjabi",
"local_name": "ਪੰਜਾਬੀ"
},
{
"code": "pl",
"english_name": "Polish",
"local_name": "Polski"
},
{
"code": "ps",
"english_name": "Pashto",
"local_name": "پښت"
},
{
"code": "pt",
"english_name": "Portuguese",
"local_name": "Português"
},
{
"code": "ro",
"english_name": "Romanian",
"local_name": "Română"
},
{
"code": "ru",
"english_name": "Russian",
"local_name": "Русский"
},
{
"code": "sd",
"english_name": "Sindhi",
"local_name": "سنڌي، سندھی, सिन्धी"
},
{
"code": "si",
"english_name": "Sinhalese",
"local_name": "සිංහල"
},
{
"code": "sk",
"english_name": "Slovak",
"local_name": "Slovenčina"
},
{
"code": "sl",
"english_name": "Slovenian",
"local_name": "Slovenščina"
},
{
"code": "sm",
"english_name": "Samoan",
"local_name": "gagana fa'a Samoa"
},
{
"code": "sn",
"english_name": "Shona",
"local_name": "chiShona"
},
{
"code": "so",
"english_name": "Somali",
"local_name": "Soomaaliga"
},
{
"code": "sq",
"english_name": "Albanian",
"local_name": "Shqip"
},
{
"code": "sr",
"english_name": "Serbian",
"local_name": "Српски"
},
{
"code": "st",
"english_name": "Southern Sotho",
"local_name": "seSotho"
},
{
"code": "su",
"english_name": "Sundanese",
"local_name": "Sundanese"
},
{
"code": "sv",
"english_name": "Swedish",
"local_name": "Svenska"
},
{
"code": "sw",
"english_name": "Swahili",
"local_name": "Kiswahili"
},
{
"code": "ta",
"english_name": "Tamil",
"local_name": "தமிழ்"
},
{
"code": "te",
"english_name": "Telugu",
"local_name": "తెలుగు"
},
{
"code": "tg",
"english_name": "Tajik",
"local_name": "Тоҷикӣ"
},
{
"code": "th",
"english_name": "Thai",
"local_name": "ภาษาไทย"
},
{
"code": "tl",
"english_name": "Tagalog",
"local_name": "Tagalog"
},
{
"code": "to",
"english_name": "Tongan",
"local_name": "faka-Tonga"
},
{
"code": "tr",
"english_name": "Turkish",
"local_name": "Türkçe"
},
{
"code": "tt",
"english_name": "Tatar",
"local_name": "Tatar"
},
{
"code": "tw",
"english_name": "Traditional Chinese",
"local_name": "中文 (繁體)"
},
{
"code": "ty",
"english_name": "Tahitian",
"local_name": "te reo Tahiti, te reo Māʼohi"
},
{
"code": "uk",
"english_name": "Ukrainian",
"local_name": "Українська"
},
{
"code": "ur",
"english_name": "Urdu",
"local_name": "اردو"
},
{
"code": "uz",
"english_name": "Uzbek",
"local_name": "O'zbek"
},
{
"code": "vi",
"english_name": "Vietnamese",
"local_name": "Tiếng Việt"
},
{
"code": "xh",
"english_name": "Xhosa",
"local_name": "isiXhosa"
},
{
"code": "yi",
"english_name": "Yiddish",
"local_name": "ייִדיש"
},
{
"code": "yo",
"english_name": "Yoruba",
"local_name": "Yorùbá"
},
{
"code": "zh",
"english_name": "Simplified Chinese",
"local_name": "中文 (简体)"
},
{
"code": "zu",
"english_name": "Zulu",
"local_name": "isiZulu"
}
]

View File

@@ -0,0 +1,300 @@
[
{
"name": "Simple tag #1",
"body": "<p>Hello, <b>this is</b> a test!</p>",
"expected": [
{
"t": 1,
"w": "Hello, "
},
{
"t": 1,
"w": "this is"
},
{
"t": 1,
"w": " a test!"
}
]
},
{
"name": "Simple tag #2",
"body": "<p>Hello, <strong>this is</strong> a test!</p>",
"expected": [
{
"t": 1,
"w": "Hello, "
},
{
"t": 1,
"w": "this is"
},
{
"t": 1,
"w": " a test!"
}
]
},
{
"name": "Simple tag #3",
"body": "<p>Hello, <em>this is</em> a test!</p>",
"expected": [
{
"t": 1,
"w": "Hello, "
},
{
"t": 1,
"w": "this is"
},
{
"t": 1,
"w": " a test!"
}
]
},
{
"name": "Simple tag #4",
"body": "<p>This is a normal sentence</p>",
"expected": [
{
"t": 1,
"w": "This is a normal sentence"
}
]
},
{
"name": "Nested simple tags",
"body": "<p>Hello, <i><b>this is</b></i> a test!</p>",
"expected": [
{
"t": 1,
"w": "Hello, "
},
{
"t": 1,
"w": "this is"
},
{
"t": 1,
"w": " a test!"
}
]
},
{
"name": "Nested tags 2",
"body": "<p>This is a sentence with <strong>bolded</strong> text.</p>",
"expected": [
{
"t": 1,
"w": "This is a sentence with "
},
{
"t": 1,
"w": "bolded"
},
{
"t": 1,
"w": " text."
}
]
},
{
"name": "Nested tags 3",
"body": "<p>This is a sentence with <strong>bolded</strong> text and <em>italic text</em> and <div>other</div> text.</p>",
"expected": [
{
"t": 1,
"w": "This is a sentence with "
},
{
"t": 1,
"w": "bolded"
},
{
"t": 1,
"w": " text and "
},
{
"t": 1,
"w": "italic text"
},
{
"t": 1,
"w": " and "
},
{
"t": 1,
"w": "other"
},
{
"t": 1,
"w": " text."
}
]
},
{
"name": "Nested tags 4",
"body": "<p><strong>Everything is important</strong></p>",
"expected": [
{
"t": 1,
"w": "Everything is important"
}
]
},
{
"name": "Nested tags 5",
"body": "<p>We believe <strong>everything is <em>really</em> important</strong></p>",
"expected": [
{
"t": 1,
"w": "We believe "
},
{
"t": 1,
"w": "everything is "
},
{
"t": 1,
"w": "really"
},
{
"t": 1,
"w": " important"
}
]
},
{
"name": "Nested tags 6",
"body": "<p>We believe <strong><strong>everything</strong></strong><em><em> is important</em></em></p>",
"expected": [
{
"t": 1,
"w": "We believe "
},
{
"t": 1,
"w": "everything"
},
{
"t": 1,
"w": " is important"
}
]
},
{
"name": "Nested tags 7",
"body": "<p><abbr><i></i><i></i><strong><strong>Hello, </strong></strong><em><em>how are you</em></em><i></i></abbr></p>",
"expected": [
{
"t": 1,
"w": "Hello, "
},
{
"t": 1,
"w": "how are you"
}
]
},
{
"name": "Nested tags 8",
"body": "<p><abbr><i></i><i></i><b><strong><strong>Hello, </strong></strong><em><em>how are you</em></em></b><i></i></abbr></p>",
"expected": [
{
"t": 1,
"w": "Hello, "
},
{
"t": 1,
"w": "how are you"
}
]
},
{
"name": "Nested tags 9",
"body": "<p><abbr><i></i><i></i><b><strong><strong>Hello, </strong></strong></b><i></i></abbr></p>",
"expected": [
{
"t": 1,
"w": "Hello, "
}
]
},
{
"name": "Link tag",
"body": "<p>Hello, <a href='#'>this is</a> a test!</p>",
"expected": [
{
"t": 1,
"w": "Hello, "
},
{
"t": 1,
"w": "this is"
},
{
"t": 1,
"w": " a test!"
}
]
},
{
"name": "Button tag",
"body": "<form><button value='Click me!'></button></form>",
"expected": [
{
"t": 2,
"w": "Click me!"
}
]
},
{
"name": "Input tag",
"body": "<form><input type='text' placeholder='This is a placeholder!'></form>",
"expected": [
{
"t": 3,
"w": "This is a placeholder!"
}
]
},
{
"name": "Meta tag",
"body": "<meta name='description' content='This is a website description!'>",
"expected": [
{
"t": 4,
"w": "This is a website description!"
}
]
},
{
"name": "Image tag",
"body": "<p><img src='/an-image.png' alt='This is an image!'></p>",
"expected": [
{
"t": 7,
"w": "This is an image!"
},
{
"t": 6,
"w": "/an-image.png"
}
]
},
{
"name": "Link tag with pdf",
"body": "<p><a href='/my-document.pdf'>Click here!</a></p>",
"expected": [
{
"t": 8,
"w": "/my-document.pdf"
},
{
"t": 1,
"w": "Click here!"
}
]
}
]

View File

@@ -0,0 +1,226 @@
[
{
"name": "Simple tag #1",
"body": "<p>Hello, <b>this is</b> a test!</p>",
"expected": [
{
"t": 1,
"w": "Hello, <b>this is</b> a test!"
}
]
},
{
"name": "Simple tag #2",
"body": "<p>Hello, <strong>this is</strong> a test!</p>",
"expected": [
{
"t": 1,
"w": "Hello, <strong>this is</strong> a test!"
}
]
},
{
"name": "Simple tag #3",
"body": "<p>Hello, <em>this is</em> a test!</p>",
"expected": [
{
"t": 1,
"w": "Hello, <em>this is</em> a test!"
}
]
},
{
"name": "Simple tag #4",
"body": "<p>This is a normal sentence</p>",
"expected": [
{
"t": 1,
"w": "This is a normal sentence"
}
]
},
{
"name": "Nested simple tags",
"body": "<p>Hello, <i><b>this is</b></i> a test!</p>",
"expected": [
{
"t": 1,
"w": "Hello, <i><b>this is</b></i> a test!"
}
]
},
{
"name": "Nested tags 2",
"body": "<p>This is a sentence with <strong>bolded</strong> text.</p>",
"expected": [
{
"t": 1,
"w": "This is a sentence with <strong>bolded</strong> text."
}
]
},
{
"name": "Nested tags 3",
"body": "<p>This is a sentence with <strong>bolded</strong> text and <em>italic text</em> and <div>other</div> text.</p>",
"expected": [
{
"t": 1,
"w": "This is a sentence with <strong>bolded</strong> text and <em>italic text</em> and "
},
{
"t": 1,
"w": "other"
},
{
"t": 1,
"w": " text."
}
]
},
{
"name": "Nested tags 4",
"body": "<p><strong>Everything is important</strong></p>",
"expected": [
{
"t": 1,
"w": "Everything is important"
}
]
},
{
"name": "Nested tags 5",
"body": "<p>We believe <strong>everything is <em>really</em> important</strong></p>",
"expected": [
{
"t": 1,
"w": "We believe <strong>everything is <em>really</em> important</strong>"
}
]
},
{
"name": "Nested tags 6",
"body": "<p>We believe <strong><strong>everything</strong></strong><em><em> is important</em></em></p>",
"expected": [
{
"t": 1,
"w": "We believe <strong><strong>everything</strong></strong><em><em> is important</em></em>"
}
]
},
{
"name": "Nested tags 7",
"body": "<p><abbr><i></i><i></i><strong><strong>Hello, </strong></strong><em><em>how are you</em></em><i></i></abbr></p>",
"expected": [
{
"t": 1,
"w": "<i></i><i></i><strong><strong>Hello, </strong></strong><em><em>how are you</em></em><i></i>"
}
]
},
{
"name": "Nested tags 8",
"body": "<p><abbr><i></i><i></i><b><strong><strong>Hello, </strong></strong><em><em>how are you</em></em></b><i></i></abbr></p>",
"expected": [
{
"t": 1,
"w": "<strong><strong>Hello, </strong></strong><em><em>how are you</em></em>"
}
]
},
{
"name": "Nested tags 9",
"body": "<p><abbr><i></i><i></i><b><strong><strong>Hello, </strong></strong></b><i></i></abbr></p>",
"expected": [
{
"t": 1,
"w": "Hello, "
}
]
},
{
"name": "Nested tags 10",
"body": "<p><abbr><i></i><i></i><b><strong> <strong>Hello, </strong></strong> <em> <em> how are you</em></em></b><i></i></abbr></p>",
"expected": [
{
"t": 1,
"w": "<strong> <strong>Hello, </strong></strong> <em> <em> how are you</em></em>"
}
]
},
{
"name": "Link tag",
"body": "<p>Hello, <a href='#'>this is</a> a test!</p>",
"expected": [
{
"t": 1,
"w": "Hello, "
},
{
"t": 1,
"w": "this is"
},
{
"t": 1,
"w": " a test!"
}
]
},
{
"name": "Button tag",
"body": "<form><button value='Click me!'></button></form>",
"expected": [
{
"t": 2,
"w": "Click me!"
}
]
},
{
"name": "Input tag",
"body": "<form><input type='text' placeholder='This is a placeholder!'></form>",
"expected": [
{
"t": 3,
"w": "This is a placeholder!"
}
]
},
{
"name": "Meta tag",
"body": "<meta name='description' content='This is a website description!'>",
"expected": [
{
"t": 4,
"w": "This is a website description!"
}
]
},
{
"name": "Image tag",
"body": "<p><img src='/an-image.png' alt='This is an image!'></p>",
"expected": [
{
"t": 7,
"w": "This is an image!"
},
{
"t": 6,
"w": "/an-image.png"
}
]
},
{
"name": "Link tag with pdf",
"body": "<p><a href='/my-document.pdf'>Click here!</a></p>",
"expected": [
{
"t": 8,
"w": "/my-document.pdf"
},
{
"t": 1,
"w": "Click here!"
}
]
}
]

View File

@@ -0,0 +1,176 @@
[
{
"name": "Simple tag #1",
"body": "<p>Hello, <b>this is</b> a test!</p>",
"expected": [
{
"t": 1,
"w": "Hello, &lt;b&gt;this is&lt;/b&gt; a test!"
}
]
},
{
"name": "Simple tag #2",
"body": "<p>Hello, <strong>this is</strong> a test!</p>",
"expected": [
{
"t": 1,
"w": "Hello, &lt;strong&gt;this is&lt;/strong&gt; a test!"
}
]
},
{
"name": "Simple tag #3",
"body": "<p>Hello, <em>this is</em> a test!</p>",
"expected": [
{
"t": 1,
"w": "Hello, &lt;em&gt;this is&lt;/em&gt; a test!"
}
]
},
{
"name": "Simple tag #4",
"body": "<p>This is a normal sentence</p>",
"expected": [
{
"t": 1,
"w": "This is a normal sentence"
}
]
},
{
"name": "Nested simple tags",
"body": "<p>Hello, <i><b>this is</b></i> a test!</p>",
"expected": [
{
"t": 1,
"w": "Hello, &lt;i&gt;&lt;b&gt;this is&lt;/b&gt;&lt;/i&gt; a test!"
}
]
},
{
"name": "Nested tags 2",
"body": "<p>This is a sentence with <strong>bolded</strong> text.</p>",
"expected": [
{
"t": 1,
"w": "This is a sentence with &lt;strong&gt;bolded&lt;/strong&gt; text."
}
]
},
{
"name": "Nested tags 3",
"body": "<p>This is a sentence with <strong>bolded</strong> text and <em>italic text</em> and <div>other</div> text.</p>",
"expected": [
{
"t": 1,
"w": "This is a sentence with &lt;strong&gt;bolded&lt;/strong&gt; text and &lt;em&gt;italic text&lt;/em&gt; and "
},
{
"t": 1,
"w": "other"
},
{
"t": 1,
"w": " text."
}
]
},
{
"name": "Nested tags 4",
"body": "<p><strong>Everything is important</strong></p>",
"expected": [
{
"t": 1,
"w": "&lt;strong&gt;Everything is important&lt;/strong&gt;"
}
]
},
{
"name": "Nested tags 5",
"body": "<p>We believe <strong>everything is <em>really</em> important</strong></p>",
"expected": [
{
"t": 1,
"w": "We believe &lt;strong&gt;everything is &lt;em&gt;really&lt;/em&gt; important&lt;/strong&gt;"
}
]
},
{
"name": "Link tag",
"body": "<p>Hello, <a href='#'>this is</a> a test!</p>",
"expected": [
{
"t": 1,
"w": "Hello, "
},
{
"t": 1,
"w": "this is"
},
{
"t": 1,
"w": " a test!"
}
]
},
{
"name": "Button tag",
"body": "<form><button value='Click me!'></button></form>",
"expected": [
{
"t": 2,
"w": "Click me!"
}
]
},
{
"name": "Input tag",
"body": "<form><input type='text' placeholder='This is a placeholder!'></form>",
"expected": [
{
"t": 3,
"w": "This is a placeholder!"
}
]
},
{
"name": "Meta tag",
"body": "<meta name='description' content='This is a website description!'>",
"expected": [
{
"t": 4,
"w": "This is a website description!"
}
]
},
{
"name": "Image tag",
"body": "<p><img src='/an-image.png' alt='This is an image!'></p>",
"expected": [
{
"t": 7,
"w": "This is an image!"
},
{
"t": 6,
"w": "/an-image.png"
}
]
},
{
"name": "Link tag with pdf",
"body": "<p><a href='/my-document.pdf'>Click here!</a></p>",
"expected": [
{
"t": 8,
"w": "/my-document.pdf"
},
{
"t": 1,
"w": "Click here!"
}
]
}
]

View File

@@ -0,0 +1,458 @@
[
{
"name": "Simple tag #1",
"body": "<p>Hello, <b>this is</b> a test!</p>",
"expected": [
{
"t": 1,
"w": "Hello, <b wg-1=\"\">this is</b> a test!"
}
]
},
{
"name": "Simple tag #2",
"body": "<p>Hello, <strong>this is</strong> a test!</p>",
"expected": [
{
"t": 1,
"w": "Hello, <strong wg-1=\"\">this is</strong> a test!"
}
]
},
{
"name": "Simple tag #3",
"body": "<p>Hello, <em>this is</em> a test!</p>",
"expected": [
{
"t": 1,
"w": "Hello, <em wg-1=\"\">this is</em> a test!"
}
]
},
{
"name": "Simple tag #4",
"body": "<p>This is a normal sentence</p>",
"expected": [
{
"t": 1,
"w": "This is a normal sentence"
}
]
},
{
"name": "Nested simple tags",
"body": "<p>Hello, <i><b>this is</b></i> a test!</p>",
"expected": [
{
"t": 1,
"w": "Hello, <i wg-1=\"\"><b wg-2=\"\">this is</b></i> a test!"
}
]
},
{
"name": "Nested tags 2",
"body": "<p>This is a sentence with <strong>bolded</strong> text.</p>",
"expected": [
{
"t": 1,
"w": "This is a sentence with <strong wg-1=\"\">bolded</strong> text."
}
]
},
{
"name": "Nested tags 3",
"body": "<p>This is a sentence with <strong>bolded</strong> text and <em>italic text</em> and other text.</p>",
"expected": [
{
"t": 1,
"w": "This is a sentence with <strong wg-1=\"\">bolded</strong> text and <em wg-2=\"\">italic text</em> and other text."
}
]
},
{
"name": "Nested tags 4",
"body": "<p><strong>Everything is important</strong></p>",
"expected": [
{
"t": 1,
"w": "Everything is important"
}
]
},
{
"name": "Nested tags 5",
"body": "<p>We believe <strong>everything is <em>really</em> important</strong></p>",
"expected": [
{
"t": 1,
"w": "We believe <strong wg-1=\"\">everything is <em wg-2=\"\">really</em> important</strong>"
}
]
},
{
"name": "Nested tags 6",
"body": "<p>We believe <strong><strong>everything</strong></strong><em><em> is important</em></em></p>",
"expected": [
{
"t": 1,
"w": "We believe <strong wg-1=\"\"><strong wg-2=\"\">everything</strong></strong><em wg-3=\"\"><em wg-4=\"\"> is important</em></em>"
}
]
},
{
"name": "Nested tags 7",
"body": "<p><abbr><i></i><i></i><strong><strong>Hello, </strong></strong><em><em>how are you</em></em><i></i></abbr></p>",
"expected": [
{
"t": 1,
"w": "<i wg-1=\"\"></i><i wg-2=\"\"></i><strong wg-3=\"\"><strong wg-4=\"\">Hello, </strong></strong><em wg-5=\"\"><em wg-6=\"\">how are you</em></em><i wg-7=\"\"></i>"
}
]
},
{
"name": "Nested tags 8",
"body": "<p><abbr><i></i><i></i><b><strong><strong>Hello, </strong></strong><em><em>how are you</em></em></b><i></i></abbr></p>",
"expected": [
{
"t": 1,
"w": "<strong wg-1=\"\"><strong wg-2=\"\">Hello, </strong></strong><em wg-3=\"\"><em wg-4=\"\">how are you</em></em>"
}
]
},
{
"name": "Nested tags 9",
"body": "<p><abbr><i></i><i></i><b><strong><strong>Hello, </strong></strong></b><i></i></abbr></p>",
"expected": [
{
"t": 1,
"w": "Hello, "
}
]
},
{
"name": "Nested tags 10",
"body": " <p><b>Hello </b><b>this is</b></p><p>bonjour</p><p><b>Hi </b><b>we are</b></p> ",
"expected": [
{
"t": 1,
"w": "<b wg-1=\"\">Hello </b><b wg-2=\"\">this is</b>"
},
{
"t": 1,
"w": "bonjour"
},
{
"t": 1,
"w": "<b wg-1=\"\">Hi </b><b wg-2=\"\">we are</b>"
}
]
},
{
"name": "Nested tags 11",
"body": " <p><b>Hello </b> <b>this is</b></p> <i> </i> <p>bonjour</p><p><b>Hi </b><b>we are</b></p> ",
"expected": [
{
"t": 1,
"w": "<b wg-1=\"\">Hello </b> <b wg-2=\"\">this is</b>"
},
{
"t": 1,
"w": "bonjour"
},
{
"t": 1,
"w": "<b wg-1=\"\">Hi </b><b wg-2=\"\">we are</b>"
}
]
},
{
"name": "Nested tags 12",
"body": " <p> <b>Hello</b> <i> </i> <i></i></p><p>This</p><p>is</p> ",
"expected": [
{
"t": 1,
"w": "Hello"
},
{
"t": 1,
"w": "This"
},
{
"t": 1,
"w": "is"
}
]
},
{
"name": "Nested tags 13",
"body": " <p><b>8</b><b> Hello </b></p><p> Hi</p><p>Cool</p>",
"expected": [
{
"t": 1,
"w": "<b wg-1=\"\">8</b><b wg-2=\"\"> Hello </b>"
},
{
"t": 1,
"w": " Hi"
},
{
"t": 1,
"w": "Cool"
}
]
},
{
"name": "Nested tags 14",
"body": "<li><a><h2>Banho Floral</h2><span>A first link</span></a><a>Another link</a></li>",
"expected": [
{
"t": 1,
"w": "Banho Floral"
},
{
"t": 1,
"w": "A first link"
},
{
"t": 1,
"w": "Another link"
}
]
},
{
"name": "Nested tags 15",
"body": "<p> <b> This is another nested test </b><br></p>",
"expected": [
{
"t": 1,
"w": " This is another nested test "
}
]
},
{
"name": "Nested tags 16",
"body": "<p>This <strong>is</strong> another nested test<br></p>",
"expected": [
{
"t": 1,
"w": "This <strong wg-1=\"\">is</strong> another nested test<br wg-2=\"\">"
}
]
},
{
"name": "Nested tags 17",
"body": "<p>This ending tag must not be here<br></p>",
"expected": [
{
"t": 1,
"w": "This ending tag must not be here"
}
]
},
{
"name": "Tag with br",
"body": "<p>Hello, <br> a test!</p>",
"expected": [
{
"t": 1,
"w": "Hello, <br wg-1=\"\"> a test!"
}
]
},
{
"name": "Tag with br",
"body": "<p>Hello, <br> a test! how are <b>you</b></p>",
"expected": [
{
"t": 1,
"w": "Hello, <br wg-1=\"\"> a test! how are <b wg-2=\"\">you</b>"
}
]
},
{
"name": "Exclude tags 1",
"body": " <p><b>Hello </b><b data-wg-notranslate>man</b></p> ",
"expected": [
{
"t": 1,
"w": "Hello "
}
]
},
{
"name": "Link tag",
"body": "<p>Hello, <a href='#'>this is</a> a test!</p>",
"expected": [
{
"t": 1,
"w": "Hello, <a wg-1=\"\">this is</a> a test!"
}
]
},
{
"name": "Link tag with title",
"body": "<p>Hello, <a href='#' title='title needs translation'>this is</a> a test!</p>",
"expected": [
{
"t": 1,
"w": "title needs translation"
},
{
"t": 1,
"w": "Hello, <a wg-1=\"\">this is</a> a test!"
}
]
},
{
"name": "Link tag with title 2",
"body": "<p>Hello, <b><a href='#' class='translate' title='translate'>this is</a> a <a href='#' title='link needs translation'>link</a></b> and a test!</p>",
"expected": [
{
"t": 1,
"w": "translate"
},
{
"t": 1,
"w": "link needs translation"
},
{
"t": 1,
"w": "Hello, <b wg-1=\"\"><a wg-2=\"\">this is</a> a <a wg-3=\"\">link</a></b> and a test!"
}
]
},
{
"name": "Button tag",
"body": "<form><button value='Click me!'></button></form>",
"expected": [
{
"t": 2,
"w": "Click me!"
}
]
},
{
"name": "Input tag",
"body": "<form><input type='text' placeholder='This is a placeholder!'></form>",
"expected": [
{
"t": 3,
"w": "This is a placeholder!"
}
]
},
{
"name": "Meta tag",
"body": "<meta name='description' content='This is a website description!'>",
"expected": [
{
"t": 4,
"w": "This is a website description!"
}
]
},
{
"name": "Image tag",
"body": "<p><img src='/an-image.png' alt='This is an image!'></p>",
"expected": [
{
"t": 7,
"w": "This is an image!"
},
{
"t": 6,
"w": "/an-image.png"
}
]
},
{
"name": "Link tag with pdf",
"body": "<p><a href=\"/my-document.pdf\">Click here!</a></p>",
"expected": [
{
"t": 8,
"w": "/my-document.pdf"
},
{
"t": 1,
"w": "Click here!"
}
]
},
{
"name": "Link tag with pdf 2",
"body": "<p>Hello! <a href=\"/my-document.pdf\">Click here!</a></p>",
"expected": [
{
"t": 8,
"w": "/my-document.pdf"
},
{
"t": 1,
"w": "Hello! <a wg-1=\"\">Click here!</a>"
}
]
},
{
"name": "Tag with new line and blanks",
"body": "<p> \n\n <strong>test</strong> \n\n </p>",
"expected": [
{
"t": 1,
"w": "test"
}
]
},
{
"name": "Sentence with a comment",
"body": "<p><!--This is a comment-->This is <b>nice</b> and easy</p>",
"expected": [
{
"t": 1,
"w": "This is <b wg-1=\"\">nice</b> and easy"
}
]
},
{
"name": "Sentence with empty node",
"body": "<p><a href=\"#\"> <span>Hello</span></a></p><h2>That's a test</h2><p>test</p>",
"expected": [
{
"t": 1,
"w": "Hello"
},
{
"t": 1,
"w": "That's a test"
},
{
"t": 1,
"w": "test"
}
]
},
{
"name": "Sentence with 2 comments",
"body": "<h2><!-- Comment 1 --><!--Comment2-->Hi there</h2>",
"expected": [
{
"t": 1,
"w": "Hi there"
}
]
},
{
"name": "Sentence with a number merged",
"body": "<div><a><b>1</b><b>Hallo</b></a></div><p>Wo bist du?</p>",
"expected": [
{
"t": 1,
"w": "<b wg-1=\"\">1</b><b wg-2=\"\">Hallo</b>"
},
{
"t": 1,
"w": "Wo bist du?"
}
]
}
]

View File

@@ -0,0 +1,21 @@
{
"v1": [],
"v2": [
"ABBR",
"ACRONYM",
"B",
"BDO",
"BIG",
"CITE",
"EM",
"I",
"KBD",
"Q",
"SMALL",
"STRONG",
"SUB",
"SUP",
"U"
],
"v3": ["A", "BDI", "BR", "DEL", "DFN", "INS", "S", "SPAN"]
}

View File

@@ -0,0 +1,13 @@
{
"OTHER": 0,
"TEXT": 1,
"VALUE": 2,
"PLACEHOLDER": 3,
"META_CONTENT": 4,
"IFRAME_SRC": 5,
"IMG_SRC": 6,
"IMG_ALT": 7,
"PDF_HREF": 8,
"PAGE_TITLE": 9,
"EXTERNAL_LINK": 10
}

View File

@@ -0,0 +1,28 @@
// NOTE: This file should not contain any data itself.
var labelKey = "english_name"; // local_name | english_name
var wordType = require("./data/word-type.json");
var cases = {
v1: require("./data/cases/cases-v1.json"),
v2: require("./data/cases/cases-v2-js.json"),
v3: require("./data/cases/cases-v3.json")
};
var languages = require("./data/available-languages.json")
.sort(function(a, b) {
return a[labelKey].localeCompare(b[labelKey]);
})
.map(function(language) {
return {
label: language[labelKey],
value: language.code
};
});
module.exports = {
cases: cases,
mergeNodesList: require("./mergeNodesList").mergeNodesList,
languages: languages,
wordType: wordType
};

View File

@@ -0,0 +1,45 @@
<?php
namespace Weglot;
class TranslationDefinitions
{
public static $languages;
public static $cases;
public static $mergeNodesList;
private static $labelKey = "english_name";
private static function loadJSON($key)
{
return json_decode(file_get_contents(__DIR__ . "/data/" . $key . ".json"), true);
}
private static function sortedJSONArray($pathKey, $sortKey, $sortOrder = SORT_ASC)
{
$array = self::loadJSON($pathKey);
array_multisort(array_map(function ($el) use ($sortKey) {
return $el[$sortKey];
}, $array), $sortOrder, $array);
return $array;
}
static function init()
{
self::$languages = array_map(function ($language) {
return array(
'label' => $language[self::$labelKey],
'value' => $language['code']
);
}, self::sortedJSONArray("available-languages", self::$labelKey));
self::$cases = array(
'v1' => self::loadJSON("cases/cases-v1"),
'v2' => self::loadJSON("cases/cases-v2-php"),
'v3' => self::loadJSON("cases/cases-v3")
);
self::$mergeNodesList = self::loadJSON("merge-nodes");
}
}
TranslationDefinitions::init();

View File

@@ -0,0 +1,7 @@
{
"compilerOptions": {
"module": "commonjs",
"resolveJsonModule": true,
"checkJs": true
}
}

View File

@@ -0,0 +1,4 @@
// NOTE: This file should not contain any data itself.
var mergeNodesList = require("./data/merge-nodes.json");
mergeNodesList.v2.unshift("#text");
exports.mergeNodesList = mergeNodesList;

View File

@@ -0,0 +1,15 @@
{
"name": "weglot-translation-definitions",
"version": "2.3.2",
"main": "index.js",
"private": true,
"repository": "https://github.com/weglot/weglot-translation-definitions.git",
"author": "Mehdi Rejraji <mehdi.rejraji@gmail.com>",
"license": "MIT",
"scripts": {
"test": "echo \"Running tests before publishing...\"",
"preversion": "yarn test",
"postversion": "git push origin v$npm_package_version",
"update-languages": "http --pretty=format https://api.weglot.com/public/languages > data/available-languages.json"
}
}

View File

@@ -0,0 +1,20 @@
<?php
$finder = PhpCsFixer\Finder::create()
->files()
->in(__DIR__)
->exclude('vendor')
->notName("*.txt")
->name('*.php')
->ignoreDotFiles(true)
->ignoreVCS(true);
;
return PhpCsFixer\Config::create()
->setRules([
'@PSR1' => true,
'@PSR2' => true,
'array_syntax' => ['syntax' => 'short'],
'no_alternative_syntax' => true
])
->setFinder($finder);

View File

@@ -0,0 +1,206 @@
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
## [Unreleased]
## [1.0.7] - 2020-08-12
### Added
- Add External links translation on iframe
- Add brazilian portuguese
## [1.0.6] - 2020-07-07
### Added
- Add External links translation
### Changed
- Simplify Regex for default regex checker (HTML template and JSON LD)
### Fixed
- Fix a rare bug with comments inside nodes
## [1.0.5] - 2020-04-14
### Added
- Add callback mechanism on regex checker
- Add support for array in JSON
- Add a type 9 for title tag
### Fixed
- Fix a rare bug when some empty nodes
- Fix error when sentence is split because of comment
## [1.0.3] - 2019-12-16
### Changed
- Fixed formatter on JSON source, only apply previous change to TEXT regex
## [1.0.2] - 2019-12-16
### Changed
- Fixed formatter on text regex when it contain '#'
## [1.0.1] - 2019-12-03
### Changed
- Fixed formatter on text regex to only take word
## [0.5.21] - 2019-03-12
### Added
- Util Regex for excluded paths
### Changed
- Update translation engine
## [0.5.12] - 2018-09-19
Add escape property on dom checker
## [0.5.11] - 2018-07-31
### Changed
Better API errors management
## [0.5.10] - ????-??-??
???
## [0.5.9] - 2018-07-19
### Changed
- Cleaning tags html entities before rendering
- Fix URL and infinite loop bug
## [0.5.8] - 2018-06-26
### Changed
- Simplify code and fix all ignore nodes related problems
### Fixed
- Forgot noscript & code in Text checker
## [0.5.7] - 2018-06-12
### Changed
- Client.HttpClient: Using new header system (Weglot-Context)
- Client.Profile: Setting ignoredNodes behavior as default one
### Fixed
- Parser: fixes some checkers (Check.Placeholder / Check.Text) & fixing AbstractDomChecker in checkers list
- Parser.ignoredNodes: Fixing replacement method to allow more content (class or other attributes) in skipped tags
## [0.5.6] - 2018-06-08
### Fixed
- Factory.Translate: fixing wrong assignation
## [0.5.5] - 2018-06-08
### Fixed
- Factory.Translate: fixing issue where PHP can returns an array not in same order as the keys are
## [0.5.4] - 2018-06-05
### Fixed
- Util.Url: missing getDefault function
## [0.5.3] - 2018-06-05
### Added
- Util.Url: adding query managment
### Changed
- Better exceptions for Translate endpoint
- Improving Util.Url structure
- Better travis tests (with low deps for PHP 5.4)
### Fixed
- Unit tests where break due to no trailing slash
## [0.5.2] - 2018-05-31
### Fixed
- Util.Url: nested Url prefix was in baseUrl
## [0.5.1] - 2018-05-28
### Fixed
- Util.Url: Adding Port managment
## [0.5.0] - 2018-05-28
### Added
- Util.Url: `getForLanguage($code)` function to get given language url base on current `Url` instance
- Api.Languages: adding data for RTL (right to left) languages and access in API objects
### Changed
- Util.Url: Local caching for `currentRequestAllUrls()` function
- Updating `composer.json`
## [0.4.2] - 2018-05-21
### Fixed
- Util.Url: handling case where prefix path has trailing slash
### Added
- Tests: Unit tests for Util.Url to check when prefix path as trailing slash
## [0.4.1] - 2018-05-15
### Fixed
- Util.Url: fixing error when path is also host root
## [0.4.0] - 2018-05-15
### Added
- Util.Url: implementing Url utility class ! with all unit tests needed
- Tests: adding unit tests for Util\JsonLd class
## [0.3.1] - 2018-05-11
### Changed
- Translate: when response if not array, we throw an ApiError
### Fixed
- Parser: if simple_html_dom can't parse the HTML, we return raw HTML with no modifications
## [0.3] - 2018-05-07
### Added
- Client: Adding bundled CA cert for cURL
### Changed
- Travis: Improving script (cleaner / easier to understand)
- Client: Guzzle removed in favor of cURL implementation
## [0.2.2] - 2018-05-07
### Fixed
- Translate/Cache: Cached words aren't unique anymore (before, only one pair could work)
## [0.2.1] - 2018-04-30
### Fixed
- Parser: Excluding php tags from text checker
## [0.2] - 2018-04-26
### Added
- Util to fetch Site contents through `Site::get`
- cURL & OpenSSL versions inside user-agent for debugging purposes
### Changed
- Parser: excludeBlocks formatter is started only if we have excludeBlocks
- Parser: adding DomCheckerProvider to Parser. Like that people can add their own Checkers
- README: updated getting started to use Parser example, and adding documentation
- Caching: Improving granularity, we use cache on Endpoints to be able to cache words by words and not the full request
- Travis-CI: PHP 5.5 is no more in failures but don't run all caching tests
- CodeClimate: improving maintainability
## [0.1.2] - 2018-04-19
### Fixed
- \#7 : Parser - dynamic tooltip hover a link
## [0.1.1] - 2018-04-18
### Fixed
- ServerConfigProvider behavior changed: we do not load $_SERVER in __construct, it can disturb symfony service loading
## [0.1] - 2018-04-16
### Added
- CodeClimate configuration
- Travis configuration
- Manage API versions (through Profile class)
- Error abstraction
- Unit testing
### Changed
- Refactoring for `Parser`
- Languages endpoint: now giving full list
## [0.1-beta.2] - 2018-04-12
### Added
- examples & descriptions:
- cached-client-translate
- parsing-web-page
- simple-client-languages
- simple-client-status
- simple-client-translate
- adding README, LICENCE, CODE_OF_CONDUCT, CONTRIBUTING and github templates
## [0.1-beta.1] - 2018-04-11
### Added
- first Client version
- first endpoints:
- Translate Endpoint
- Status Endpoint
- Languages Endpoint
- client Caching through PSR-6
- importing old Parser with some refactoring

View File

@@ -0,0 +1,73 @@
# Contributor Covenant Code of Conduct
## Our Pledge
In the interest of fostering an open and welcoming environment, we as
contributors and maintainers pledge to making participation in our project and
our community a harassment-free experience for everyone, regardless of age, body
size, disability, ethnicity, gender identity and expression, level of experience,
education, socio-economic status, nationality, personal appearance, race,
religion, or sexual identity and orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment
include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or
advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic
address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable
behavior and are expected to take appropriate and fair corrective action in
response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or
reject comments, commits, code, wiki edits, issues, and other contributions
that are not aligned to this Code of Conduct, or to ban temporarily or
permanently any contributor for other behaviors that they deem inappropriate,
threatening, offensive, or harmful.
## Scope
This Code of Conduct applies both within project spaces and in public spaces
when an individual is representing the project or its community. Examples of
representing a project or community include using an official project e-mail
address, posting via an official social media account, or acting as an appointed
representative at an online or offline event. Representation of a project may be
further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting the project team at [support@weglot.com](mailto:support@weglot.com). All
complaints will be reviewed and investigated and will result in a response that
is deemed necessary and appropriate to the circumstances. The project team is
obligated to maintain confidentiality with regard to the reporter of an incident.
Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good
faith may face temporary or permanent repercussions as determined by other
members of the project's leadership.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
[homepage]: https://www.contributor-covenant.org

View File

@@ -0,0 +1,57 @@
## Contributing
:+1::tada: First off, thanks for taking the time to contribute! :tada::+1:
The following is a set of guidelines for contributing to Weglot and its packages, which are hosted in the [Weglot Organization](https://github.com/weglot) on GitHub. These are mostly guidelines, not rules. Use your best judgment, and feel free to propose changes to this document in a pull request.
### Opening an issue
Each repository provides a template for issues. First, we need to know if it's a bug report or a feature report.
Then what you expected to happen, a clear description of the problem you're facing, steps to reproduce and environment details: the client and language version are a big help.
### Submitting a pull request
Keep your changes as focused as possible. If there are multiple changes you'd like to make,
please consider submitting them as separate pull requests unless they are related to each other.
Here are a few tips to increase the likelihood of being merged:
* Fill in [the required template](PULL_REQUEST_TEMPLATE.md)
* Do not include issue numbers in the PR title
* Include screenshots and animated GIFs in your pull request whenever possible.
* Follow our [code styleguide](#styleguides).
* Document new code based on PHPDoc.
* Write tests.
* Write a [good commit message](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html).
### Styleguides
Generally, we follow the style guidelines as suggested by the official language.
However, we ask that you conform to the styles that already exist in the library.
If you wish to deviate, please explain your reasoning.
- [PSR1 Basic Coding Standard](https://www.php-fig.org/psr/psr-1/)
- [PSR2 Coding Style Guide](https://www.php-fig.org/psr/psr-2/)
- Forcing array with short syntax: `[]`
- Replace control structure alternative syntax to use braces.
Please run your code through:
[PHP CS Fixer](https://github.com/FriendsOfPHP/PHP-CS-Fixer)
We provide configuration for this tool through [`.php_cs`](./.php_cs) file.
### Security issues
If you find any security risk in the project, please open an issue or contact us at `support@weglot.com` regarding the impact.
### API Breaking changes
We care deeply about backward compatibility for our API clients libraries.
If it's necessary, we're ready to break backward compatibility,
but this should be pretty rare.
If you want to make a change that will break the backward compatibility of the API,
open an issue first to discuss it with the maintainers.
## Resources
- [Contributing to Open Source on GitHub](https://guides.github.com/activities/contributing-to-open-source/)
- [Using Pull Requests](https://help.github.com/articles/using-pull-requests/)
- [GitHub Help](https://help.github.com)

View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2018 Weglot
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -0,0 +1,243 @@
<!-- logo -->
<img src="https://cdn.weglot.com/logo/logo-hor.png" height="40" />
# PHP library
<!-- tags -->
[![WeglotSlack](https://weglot-community.now.sh/badge.svg)](https://weglot-community.now.sh/)
[![Latest Stable Version](https://poser.pugx.org/weglot/weglot-php/v/stable)](https://packagist.org/packages/weglot/weglot-php)
[![BuildStatus](https://travis-ci.com/weglot/weglot-php.svg?branch=develop)](https://travis-ci.com/weglot/weglot-php)
[![Code Climate](https://codeclimate.com/github/weglot/weglot-php/badges/gpa.svg)](https://codeclimate.com/github/weglot/weglot-php)
[![License](https://poser.pugx.org/weglot/weglot-php/license)](https://packagist.org/packages/weglot/weglot-php)
## Overview
This library allows you to quickly and easily use the Weglot API via PHP. It handle all communication with Weglot API and gives you a [fully functional Parser](#getting-started) to handle HTML pages easily.
## Requirements
- PHP version 5.6 and later
- Weglot API Key, starting at [free level](https://dashboard.weglot.com/register?origin=9)
## Installation
You can install the library via [Composer](https://getcomposer.org/). Run the following command:
```bash
composer require weglot/weglot-php
```
To use the library, use Composer's [autoload](https://getcomposer.org/doc/01-basic-usage.md#autoloading):
```php
require_once __DIR__. '/vendor/autoload.php';
```
## Getting Started
Simple usage of `Parser`:
```php
// Url to parse
$url = 'https://foo.bar/baz';
// Config with $_SERVER variables
$config = new ServerConfigProvider();
// Fetching url content
$content = '...';
// Client
$client = new Client(getenv('WG_API_KEY'));
$parser = new Parser($client, $config);
// Run the Parser
$translatedContent = $parser->translate($content, 'en', 'de');
```
For more details, check at [corresponding example](./examples/parsing-web-page/run.php) or at [documentation](https://weglot.github.io/documentation/#parser).
## Examples
For more usage examples, such as: other endpoints, caching, parsing.
You can take a look at: [examples](./examples) folder. You'll find a short README with details about each example.
## Reference
### Client
The Client is all the classes related with communication with the Weglot API
#### Client & Profile
`Weglot\Client\Client` is the main class of this library.
Basically it manage requests, and that's all.
With this class we have `Weglot\Client\Profile` which represent particularities based on API Key length.
Today we have 2 types of API Keys:
- 35-char API Keys: Normal API Keys with no custom functions enabled.
- 36-char API Keys: Adding `ignoredNodes` behavior, basically we skip some tags from being parsed as sentences (such as `strong`, `em`, ...) to make bigger sentences.
#### API
Includes all the objects to talk with the API (as input or output).
- `Weglot\Client\Api\WordEntry`: Define a single sentence within an API Object
- `Weglot\Client\Api\WordCollection`: Define multiple `WordEntry`
- `Weglot\Client\Api\LanguageEntry`: Define a single language within an API Object
- `Weglot\Client\Api\LanguageCollection`: Define multiple `LanguageEntry`
- `Weglot\Client\Api\TranslateEntry`: Define a translate interface to use as input/output of `/translate` endpoint
Here is some quick example of using some of theses:
```php
// creating some WordEntry objects
$firstWord = new WordEntry('This is a blue car', WordType::TEXT);
$secondWord = new WordEntry('This is a black car', WordType::TEXT);
// then create our TranslateEntry object to use later with /translate
$translateEntry = new TranslateEntry([
'language_from' => 'en',
'language_to' => 'de',
'title' => 'Weglot | Translate your website - Multilingual for WordPress, Shopify, ...',
'request_url' => 'https://weglot.com/',
'bot' => BotType::HUMAN
]);
$translateEntry->getInputWords()->addMany([$firstWord, $secondWord]);
```
Like you just saw, you can find quick Enums to set API-related data easier, like theses:
- `Weglot\Client\Api\Enum\WordType`: Used to provide context over where the text we wish to translate comes from.
- `Weglot\Client\Api\Enum\BotType`: Used to define the source of a request.
#### Caching
We manage Cache with one main interface: `Weglot\Client\Caching\CacheInterface` it use [PSR-6 RFC](https://www.php-fig.org/psr/psr-6/) internally.
We added one implementation of this interface within the `Weglot\Client\Caching\Cache` class which takes a PSR-6 `CacheItemPoolInterface` as store.
You can set this one from a Client method as following:
```php
$client = new Client('wg_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx');
$client->setCacheItemPool($myCacheItemPool);
```
The given `$myCacheItemPool` can be any PSR-6 compliant object. I suggest to consult [php-cache](http://www.php-cache.com/en/latest/#cache-pool-implementations) cache pool implementations that should contains the library you need to plug your cache.
#### Endpoint
Here are the class to talk with API endpoints. Today we have 3 of them:
- `Weglot\Client\Endpoint\Translate`: Used to make requests with the `/translate` endpoint
- `Weglot\Client\Endpoint\Status`: Used to make requests with the `/status` endpoint
- `Weglot\Client\Endpoint\LanguagesList`: Which is used to get all languages-related data from a "fake" API
Following our example from API Objects, here is how to use `Translate` class:
```php
$client = new Client('wg_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx');
$translateEntry = new TranslateEntry(...); // Check API part for more details about this one
$translate = new Translate($translateEntry, $client);
$translated = $translate->handle();
```
Following this example, the `$translated` object will contain a `TranslateEntry` object with all data returned from the API.
You can find [a full working example here](./examples/simple-client-translate/)
#### Factory
Theses are classes used between the endpoints classes and the returned API object.
It handles all conversion from the API that return JSON to the well formated API object.
No example here since it's only used internally.
#### HttpClient
Another internal set of classes.
Theses are composed by a simple interface to manage requests: `Weglot\Client\HttpClient`
And an implementation with cURL as the HTTP provider: `Weglot\Client\CurlClient` (this class is actually heavily inspired by Stripe's CurlClient)
### Parser
The Parser is a big part in our developer kits.
It's used to match sentences to translate from DOM and to make clean API objects to send them after through the Client.
There is no documentation for the Parser at the moment since we plan a heavy rework in next month on it, we'll make sure there is one after this rework.
### Util
There is some short classes to manage simple utilities such as:
#### Weglot\Util\JsonLd
Manage all actions related to recover & storing data in JsonLd structures
#### Weglot\Util\Server
All $_SERVER related utilities
```php
$fullUrl = Server::fullUrl($_SERVER);
// will return the current url seen by $_SERVER, for example: https://weglot.com/es/pricing
```
#### Weglot\Util\Site
Used to get contents from a distant website
#### Weglot\Util\Text
All classic Text utilities such as `contains()`
#### Weglot\Util\Url
And we've `Weglot\Util\Url` which is one of the cornerstone of url managment in our library. By fetching current url and Weglot configuration, it can serve several purposes:
- Know which language we have on the current url
- Generate urls for other languages
- Know if current url is translable or not (based on excludedUrls)
- Get all translated urls based on current url
- Generate hreflang tags based on all translated urls
Here is some quick examples:
```php
$url = new Url('https://weglot.com/es/pricing', 'en', ['fr', 'es', 'de']);
$currentLang = $url->detectCurrentLanguage();
// $currentLang will contain 'es'
$frUrl = $url->getForLanguage('fr');
// $frUrl will contain 'https://weglot.com/fr/pricing'
$translable = $url->isTranslable();
// $translable will contain true since we have no excluded urls
$url->setExcludedUrls(['/pricing']);
$translable = $url->isTranslable();
// $translable will contain false since we added `/pricing` to the excluded urls
$urls = $url->currentRequestAllUrls();
/**
* $urls will contain following array:
* Array(
* 'en' => 'https://weglot.com/pricing',
* 'fr' => 'https://weglot.com/fr/pricing',
* 'es' => 'https://weglot.com/es/pricing',
* 'de' => 'https://weglot.com/de/pricing'
* );
*/
$hreflang = $url->generateHrefLangsTags()
/**
* $hreflang will contain following string:
* <link rel="alternate" href="https://weglot.com/pricing" hreflang="en"/>
* <link rel="alternate" href="https://weglot.com/fr/pricing" hreflang="fr"/>
* <link rel="alternate" href="https://weglot.com/es/pricing" hreflang="es"/>
* <link rel="alternate" href="https://weglot.com/de/pricing" hreflang="de"/>
*/
```
##Tests
Only parser
`./vendor/codeception/codeception/codecept run -g parser`
Full test
`./vendor/codeception/codeception/codecept run`
## About
`weglot-php` is guided and supported by the Weglot Developer Team.
`weglot-php` is maintained and funded by Weglot SAS.
The names and logos for `weglot-php` are trademarks of Weglot SAS.
## License
[The MIT License (MIT)](LICENSE.txt)

View File

@@ -0,0 +1,16 @@
paths:
tests: tests
output: tests/_output
data: tests/_data
support: tests/_support
envs: tests/_envs
coverage:
enabled: true
include:
- src/*
actor_suffix: Tester
extensions:
enabled:
- Codeception\Extension\RunFailed
params:
- .env

View File

@@ -0,0 +1,67 @@
{
"name": "weglot/weglot-php",
"description": "PHP library for the Weglot API",
"homepage": "https://weglot.com/",
"type": "library",
"license": "MIT",
"authors": [
{
"name": "Baptiste Leduc",
"email": "baptiste@weglot.com",
"homepage": "https://baptiste-leduc.now.sh/",
"role": "Developer"
},
{
"name": "Thomas Deneulin",
"email": "thomas@weglot.com",
"role": "Review"
},
{
"name": "Edson Galina Fortes",
"email": "edson@weglot.com",
"role": "Developer"
}
],
"support": {
"email": "support@weglot.com",
"source": "https://github.com/weglot/weglot-php",
"docs": "https://weglot.github.io/weglot-documentation/"
},
"keywords": [
"php",
"weglot",
"weglot-library",
"translate",
"translation",
"translator",
"localization",
"languages",
"i18n"
],
"repositories": [
{
"type": "vcs",
"url": "https://github.com/weglot/weglot-translation-definitions"
},
{
"type": "vcs",
"url": "https://github.com/weglot/simple_html_dom"
}
],
"require": {
"php": ">=5.6",
"weglot/simplehtmldom": "^0.8",
"psr/cache": "^1.0",
"weglot/translation-definitions": "^2.0"
},
"autoload": {
"psr-4": {
"Weglot\\": "src/",
"Languages\\": "node_modules/@weglot/languages/dist/"
}
},
"require-dev": {
"vlucas/phpdotenv": "^2.4",
"phpstan/phpstan-deprecation-rules": "^1.1"
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,14 @@
{
"name": "weglot",
"version": "2.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"node_modules/@weglot/languages": {
"version": "1.61.1",
"resolved": "https://npm.pkg.github.com/download/@weglot/languages/1.61.1/40693ece24655279b98066106f1fdf1b5dee01f3",
"integrity": "sha512-APhZ/nDnfM9cmYJL7aWE5JDar4e6SGRclOknlhPh+Ap/n3fG5OwuezmMNfLRcKHAQ/o6QkmZRb2sjwITaZgnKA==",
"license": "UNLICENSED"
}
}
}

View File

@@ -0,0 +1,43 @@
# Weglot Languages
### Flags
Available on cdn.weglot.com
`https://cdn.weglot.com/flags/{flag_type}/{country_flag_code}.svg`
Where `flag_type` is one of
- rectangle_mat
- shiny
- circle
- square
And `country_flag_code` is country code: `gb`
Examples:
- https://cdn.weglot.com/flags/rectangle_mat/fr.svg
- https://cdn.weglot.com/flags/circle/it.svg
- https://cdn.weglot.com/flags/square/gb.svg
- https://cdn.weglot.com/flags/shiny/es.svg
### JS usage
CommonJS
```js
const { languages } = require("@weglot/languages");
```
ESM
```js
import { languages } from "@weglot/languages";
```
### How to make changes
After making a change on this repo, in order to make them available you need to do the followings:
- Change `$languages-repository-version` in `assets/css/styles.scss` with expected new version
- Run `npm run build`
- Tag your commit with expected new version

View File

@@ -0,0 +1,53 @@
const fs = require("fs");
const imagesDir = `${__dirname}/../images`;
const buildDir = `${__dirname}/../build`;
const flags = [
{
name: "square",
inputSize: "1x1",
},
{
name: "shiny",
inputSize: "4x3",
},
{
name: "circle",
inputSize: "1x1",
overlay: `<clipPath id="wg-round-mask"><circle cx="50%" cy="50%" r="50%" fill="white" /></clipPath><g clip-path="url(#wg-round-mask)">$<svg></g>`,
},
{
name: "rectangle_mat",
inputSize: "4x3",
overlay: `$<svg><rect width="100%" height="100%" style="fill:rgb(255,255,255,0.2)" />`,
},
];
if (!fs.existsSync(buildDir)) {
fs.mkdirSync(buildDir);
}
for (const flag of flags) {
const outputPath = `${buildDir}/${flag.name}`;
if (!fs.existsSync(outputPath)) {
fs.mkdirSync(outputPath);
}
const path = `${imagesDir}/${flag.inputSize}`;
const flagsData = fs.readdirSync(path).map((file) => ({
file,
path,
}));
flagsData.forEach(({ path, file }) => {
let svg = fs.readFileSync(`${path}/${file}`).toString();
if (flag.overlay) {
const regex = /(<svg(?:[^>]+)>)(?<svg>[\s\S]+)(<\/svg>)/i;
svg = svg.replace(regex, `$1${flag.overlay}$3`);
}
fs.writeFileSync(`${outputPath}/${file}`, svg);
});
}

View File

@@ -0,0 +1,38 @@
let fs = require("fs");
// Populate Languages.php
const languagesFilePath = "dist/Languages.php";
const languagesJson = JSON.parse(fs.readFileSync("data/languages.json"));
fs.openSync(languagesFilePath, 'w', 0o777);
fs.appendFileSync(
languagesFilePath,
"<?php\n\nnamespace Languages;\n\nclass Languages\n{\n public static $defaultLanguages = [\n"
);
languagesJson.languages.forEach((language, i, array) => {
fs.appendFileSync(languagesFilePath,` '${language.code}' => [\n`);
fs.appendFileSync(languagesFilePath,` 'code' => '${language.code}',\n`);
fs.appendFileSync(languagesFilePath,` 'english' => "${language.english_name}",\n`);
fs.appendFileSync(languagesFilePath,` 'local' => "${language.local_name.replace(/[""]/g, '')}",\n`);
fs.appendFileSync(languagesFilePath,` 'rtl' => ${language.rtl},\n`);
fs.appendFileSync(languagesFilePath,` ]${i !== array.length-1 ? "," : ''}\n`);
});
fs.appendFileSync(languagesFilePath, " ];\n}");
// Populate Countries.php
const countriesFilePath = "dist/Countries.php";
const CountriesJson = JSON.parse(fs.readFileSync("data/countries.json"));
fs.openSync(countriesFilePath, 'w', 0o777);
fs.appendFileSync(
countriesFilePath,
"<?php\n\nnamespace Countries;\n\nclass Countries\n{\n public static $countries = [\n"
);
CountriesJson.countries.forEach((country, i, array) => {
fs.appendFileSync(countriesFilePath,` '${country.name}' => [\n`);
fs.appendFileSync(countriesFilePath,` 'code' => '${country.code}',\n`);
fs.appendFileSync(countriesFilePath,` ]${i !== array.length-1 ? "," : ''}\n`);
});
fs.appendFileSync(countriesFilePath, " ];\n}");

View File

@@ -0,0 +1,968 @@
{
"countries": [
{
"name": "Afghanistan",
"code": "af"
},
{
"name": "Albania",
"code": "al"
},
{
"name": "Algeria",
"code": "dz"
},
{
"name": "American Samoa",
"code": "as"
},
{
"name": "Andorra",
"code": "ad"
},
{
"name": "Angola",
"code": "ao"
},
{
"name": "Antarctica",
"code": "aq"
},
{
"name": "Antigua And Barbuda",
"code": "ag"
},
{
"name": "Argentina",
"code": "ar"
},
{
"name": "Armenia",
"code": "am"
},
{
"name": "Aruba",
"code": "aw"
},
{
"name": "Australia",
"code": "au"
},
{
"name": "Austria",
"code": "at"
},
{
"name": "Azerbaijan",
"code": "az"
},
{
"name": "Bahamas",
"code": "bs"
},
{
"name": "Bahrain",
"code": "bh"
},
{
"name": "Bangladesh",
"code": "bd"
},
{
"name": "Barbados",
"code": "bb"
},
{
"name": "Belarus",
"code": "by"
},
{
"name": "Belgium",
"code": "be"
},
{
"name": "Belize",
"code": "bz"
},
{
"name": "Benin",
"code": "bj"
},
{
"name": "Bermuda",
"code": "bm"
},
{
"name": "Bhutan",
"code": "bt"
},
{
"name": "Bolivia",
"code": "bo"
},
{
"name": "Bosnia And Herzegovina",
"code": "ba"
},
{
"name": "Botswana",
"code": "bw"
},
{
"name": "Bouvet Island",
"code": "bv"
},
{
"name": "Brazil",
"code": "br"
},
{
"name": "British Indian Ocean Territory",
"code": "io"
},
{
"name": "Brunei",
"code": "bn"
},
{
"name": "Bulgaria",
"code": "bg"
},
{
"name": "Burkina Faso",
"code": "bf"
},
{
"name": "Burundi",
"code": "bi"
},
{
"name": "Cambodia",
"code": "kh"
},
{
"name": "Cameroon",
"code": "cm"
},
{
"name": "Canada",
"code": "ca"
},
{
"name": "Cape Verde",
"code": "cv"
},
{
"name": "Cayman Islands",
"code": "ky"
},
{
"name": "Central African Republic",
"code": "cf"
},
{
"name": "Chad",
"code": "td"
},
{
"name": "Chile",
"code": "cl"
},
{
"name": "China",
"code": "cn"
},
{
"name": "Christmas Island",
"code": "cx"
},
{
"name": "Cocos (keeling) Islands",
"code": "cc"
},
{
"name": "Colombia",
"code": "co"
},
{
"name": "Comoros",
"code": "km"
},
{
"name": "Congo",
"code": "cg"
},
{
"name": "Cook Islands",
"code": "ck"
},
{
"name": "Costa Rica",
"code": "cr"
},
{
"name": "Croatia",
"code": "hr"
},
{
"name": "Cuba",
"code": "cu"
},
{
"name": "Cyprus",
"code": "cy"
},
{
"name": "Czech Republic",
"code": "cz"
},
{
"name": "Denmark",
"code": "dk"
},
{
"name": "Djibouti",
"code": "dj"
},
{
"name": "Dominica",
"code": "dm"
},
{
"name": "Dominican Republic",
"code": "do"
},
{
"name": "East Timor",
"code": "tl"
},
{
"name": "Ecuador",
"code": "ec"
},
{
"name": "Egypt",
"code": "eg"
},
{
"name": "El Salvador",
"code": "sv"
},
{
"name": "Equatorial Guinea",
"code": "gq"
},
{
"name": "Eritrea",
"code": "er"
},
{
"name": "Estonia",
"code": "ee"
},
{
"name": "Ethiopia",
"code": "et"
},
{
"name": "Falkland Islands",
"code": "fk"
},
{
"name": "Faroe Islands",
"code": "fo"
},
{
"name": "Fiji Islands",
"code": "fj"
},
{
"name": "Finland",
"code": "fi"
},
{
"name": "France",
"code": "fr"
},
{
"name": "French Guiana",
"code": "gf"
},
{
"name": "French Polynesia",
"code": "pf"
},
{
"name": "French Southern Territories",
"code": "tf"
},
{
"name": "Gabon",
"code": "ga"
},
{
"name": "Gambia",
"code": "gm"
},
{
"name": "Georgia",
"code": "ge"
},
{
"name": "Germany",
"code": "de"
},
{
"name": "Ghana",
"code": "gh"
},
{
"name": "Gibraltar",
"code": "gi"
},
{
"name": "Greece",
"code": "gr"
},
{
"name": "Greenland",
"code": "gl"
},
{
"name": "Grenada",
"code": "gd"
},
{
"name": "Guadeloupe",
"code": "gp"
},
{
"name": "Guam",
"code": "gu"
},
{
"name": "Guatemala",
"code": "gt"
},
{
"name": "Guernsey",
"code": "gg"
},
{
"name": "Guinea",
"code": "gn"
},
{
"name": "Guinea Bissau",
"code": "gw"
},
{
"name": "Guyana",
"code": "gy"
},
{
"name": "Haiti",
"code": "ht"
},
{
"name": "Heard Island And Mcdonald Islands",
"code": "hm"
},
{
"name": "Holy See (vatican City State)",
"code": "va"
},
{
"name": "Honduras",
"code": "hn"
},
{
"name": "Hong Kong",
"code": "hk"
},
{
"name": "Hungary",
"code": "hu"
},
{
"name": "Iceland",
"code": "is"
},
{
"name": "India",
"code": "in"
},
{
"name": "Indonesia",
"code": "id"
},
{
"name": "Iran",
"code": "ir"
},
{
"name": "Iraq",
"code": "iq"
},
{
"name": "Ireland",
"code": "ie"
},
{
"name": "Isle Of Man",
"code": "im"
},
{
"name": "Israel",
"code": "il"
},
{
"name": "Italy",
"code": "it"
},
{
"name": "Ivory Coast",
"code": "ci"
},
{
"name": "Jamaica",
"code": "jm"
},
{
"name": "Japan",
"code": "jp"
},
{
"name": "Jersey",
"code": "je"
},
{
"name": "Jordan",
"code": "jo"
},
{
"name": "Kazakhstan",
"code": "kz"
},
{
"name": "Kenya",
"code": "ke"
},
{
"name": "Kiribati",
"code": "ki"
},
{
"name": "Kuwait",
"code": "kw"
},
{
"name": "Kyrgyzstan",
"code": "kg"
},
{
"name": "Laos",
"code": "la"
},
{
"name": "Latvia",
"code": "lv"
},
{
"name": "Lebanon",
"code": "lb"
},
{
"name": "Lesotho",
"code": "ls"
},
{
"name": "Liberia",
"code": "lr"
},
{
"name": "Libya",
"code": "ly"
},
{
"name": "Liechtenstein",
"code": "li"
},
{
"name": "Lithuania",
"code": "lt"
},
{
"name": "Luxembourg",
"code": "lu"
},
{
"name": "Macao",
"code": "mo"
},
{
"name": "Madagascar",
"code": "mg"
},
{
"name": "Malawi",
"code": "mw"
},
{
"name": "Malaysia",
"code": "my"
},
{
"name": "Maldives",
"code": "mv"
},
{
"name": "Mali",
"code": "ml"
},
{
"name": "Malta",
"code": "mt"
},
{
"name": "Marshall Islands",
"code": "mh"
},
{
"name": "Martinique",
"code": "mq"
},
{
"name": "Mauritania",
"code": "mr"
},
{
"name": "Mauritius",
"code": "mu"
},
{
"name": "Mayotte",
"code": "yt"
},
{
"name": "Mexico",
"code": "mx"
},
{
"name": "Micronesia Federated States Of",
"code": "fm"
},
{
"name": "Moldova",
"code": "md"
},
{
"name": "Monaco",
"code": "mc"
},
{
"name": "Mongolia",
"code": "mn"
},
{
"name": "Montenegro",
"code": "me"
},
{
"name": "Montserrat",
"code": "ms"
},
{
"name": "Morocco",
"code": "ma"
},
{
"name": "Mozambique",
"code": "mz"
},
{
"name": "Myanmar",
"code": "mm"
},
{
"name": "Namibia",
"code": "na"
},
{
"name": "Nauru",
"code": "nr"
},
{
"name": "Nepal",
"code": "np"
},
{
"name": "Netherlands",
"code": "nl"
},
{
"name": "New Caledonia",
"code": "nc"
},
{
"name": "New Zealand",
"code": "nz"
},
{
"name": "Nicaragua",
"code": "ni"
},
{
"name": "Niger",
"code": "ne"
},
{
"name": "Nigeria",
"code": "ng"
},
{
"name": "Niue",
"code": "nu"
},
{
"name": "Norfolk Island",
"code": "nf"
},
{
"name": "North Korea",
"code": "kp"
},
{
"name": "North Macedonia",
"code": "mk"
},
{
"name": "Norway",
"code": "no"
},
{
"name": "Oman",
"code": "om"
},
{
"name": "Pakistan",
"code": "pk"
},
{
"name": "Palau",
"code": "pw"
},
{
"name": "Palestine",
"code": "ps"
},
{
"name": "Panama",
"code": "pa"
},
{
"name": "Papua New Guinea",
"code": "pg"
},
{
"name": "Paraguay",
"code": "py"
},
{
"name": "Peru",
"code": "pe"
},
{
"name": "Philippines",
"code": "ph"
},
{
"name": "Pitcairn",
"code": "pn"
},
{
"name": "Poland",
"code": "pl"
},
{
"name": "Portugal",
"code": "pt"
},
{
"name": "Puerto Rico",
"code": "pr"
},
{
"name": "Qatar",
"code": "qa"
},
{
"name": "Quebec",
"code": "fr-ca"
},
{
"name": "Reunion",
"code": "re"
},
{
"name": "Romania",
"code": "ro"
},
{
"name": "Russian Federation",
"code": "ru"
},
{
"name": "Rwanda",
"code": "rw"
},
{
"name": "Saint Helena",
"code": "sh"
},
{
"name": "Saint Kitts And Nevis",
"code": "kn"
},
{
"name": "Saint Lucia",
"code": "lc"
},
{
"name": "Saint Pierre And Miquelon",
"code": "pm"
},
{
"name": "Saint Vincent And The Grenadines",
"code": "vc"
},
{
"name": "Samoa",
"code": "ws"
},
{
"name": "San Marino",
"code": "sm"
},
{
"name": "Sao Tome And Principe",
"code": "st"
},
{
"name": "Saudi Arabia",
"code": "sa"
},
{
"name": "Senegal",
"code": "sn"
},
{
"name": "Serbia",
"code": "rs"
},
{
"name": "Seychelles",
"code": "sc"
},
{
"name": "Sierra Leone",
"code": "sl"
},
{
"name": "Singapore",
"code": "sg"
},
{
"name": "Slovakia",
"code": "sk"
},
{
"name": "Slovenia",
"code": "si"
},
{
"name": "Solomon Islands",
"code": "sb"
},
{
"name": "Somalia",
"code": "so"
},
{
"name": "South Africa",
"code": "za"
},
{
"name": "South Georgia And The South Sandwich Islands",
"code": "gs"
},
{
"name": "South Korea",
"code": "kr"
},
{
"name": "South Sudan",
"code": "ss"
},
{
"name": "Spain",
"code": "es"
},
{
"name": "Sri Lanka",
"code": "lk"
},
{
"name": "Sudan",
"code": "sd"
},
{
"name": "Suriname",
"code": "sr"
},
{
"name": "Svalbard And Jan Mayen",
"code": "sj"
},
{
"name": "Sweden",
"code": "se"
},
{
"name": "Switzerland",
"code": "ch"
},
{
"name": "Syria",
"code": "sy"
},
{
"name": "Tajikistan",
"code": "tj"
},
{
"name": "Tanzania",
"code": "tz"
},
{
"name": "Thailand",
"code": "th"
},
{
"name": "The Democratic Republic Of Congo",
"code": "cd"
},
{
"name": "Togo",
"code": "tg"
},
{
"name": "Tokelau",
"code": "tk"
},
{
"name": "Tonga",
"code": "to"
},
{
"name": "Trinidad And Tobago",
"code": "tt"
},
{
"name": "Tunisia",
"code": "tn"
},
{
"name": "Turkey",
"code": "tr"
},
{
"name": "Turkmenistan",
"code": "tm"
},
{
"name": "Turks And Caicos Islands",
"code": "tc"
},
{
"name": "Tuvalu",
"code": "tv"
},
{
"name": "Uganda",
"code": "ug"
},
{
"name": "Ukraine",
"code": "ua"
},
{
"name": "United Arab Emirates",
"code": "ae"
},
{
"name": "United Kingdom",
"code": "gb"
},
{
"name": "United States",
"code": "us"
},
{
"name": "United States Minor Outlying Islands",
"code": "um"
},
{
"name": "Uruguay",
"code": "uy"
},
{
"name": "Uzbekistan",
"code": "uz"
},
{
"name": "Vanuatu",
"code": "vu"
},
{
"name": "Venezuela",
"code": "ve"
},
{
"name": "Vietnam",
"code": "vn"
},
{
"name": "Virgin Islands British",
"code": "vg"
},
{
"name": "Virgin Islands Us",
"code": "vi"
},
{
"name": "Wales",
"code": "gb-wls"
},
{
"name": "Wallis And Futuna",
"code": "wf"
},
{
"name": "Western Sahara",
"code": "eh"
},
{
"name": "Yemen",
"code": "ye"
},
{
"name": "Zambia",
"code": "zm"
},
{
"name": "Zimbabwe",
"code": "zw"
}
]
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,732 @@
<?php
namespace Countries;
class Countries
{
public static $countries = [
'Afghanistan' => [
'code' => 'af',
],
'Albania' => [
'code' => 'al',
],
'Algeria' => [
'code' => 'dz',
],
'American Samoa' => [
'code' => 'as',
],
'Andorra' => [
'code' => 'ad',
],
'Angola' => [
'code' => 'ao',
],
'Antarctica' => [
'code' => 'aq',
],
'Antigua And Barbuda' => [
'code' => 'ag',
],
'Argentina' => [
'code' => 'ar',
],
'Armenia' => [
'code' => 'am',
],
'Aruba' => [
'code' => 'aw',
],
'Australia' => [
'code' => 'au',
],
'Austria' => [
'code' => 'at',
],
'Azerbaijan' => [
'code' => 'az',
],
'Bahamas' => [
'code' => 'bs',
],
'Bahrain' => [
'code' => 'bh',
],
'Bangladesh' => [
'code' => 'bd',
],
'Barbados' => [
'code' => 'bb',
],
'Belarus' => [
'code' => 'by',
],
'Belgium' => [
'code' => 'be',
],
'Belize' => [
'code' => 'bz',
],
'Benin' => [
'code' => 'bj',
],
'Bermuda' => [
'code' => 'bm',
],
'Bhutan' => [
'code' => 'bt',
],
'Bolivia' => [
'code' => 'bo',
],
'Bosnia And Herzegovina' => [
'code' => 'ba',
],
'Botswana' => [
'code' => 'bw',
],
'Bouvet Island' => [
'code' => 'bv',
],
'Brazil' => [
'code' => 'br',
],
'British Indian Ocean Territory' => [
'code' => 'io',
],
'Brunei' => [
'code' => 'bn',
],
'Bulgaria' => [
'code' => 'bg',
],
'Burkina Faso' => [
'code' => 'bf',
],
'Burundi' => [
'code' => 'bi',
],
'Cambodia' => [
'code' => 'kh',
],
'Cameroon' => [
'code' => 'cm',
],
'Canada' => [
'code' => 'ca',
],
'Cape Verde' => [
'code' => 'cv',
],
'Cayman Islands' => [
'code' => 'ky',
],
'Central African Republic' => [
'code' => 'cf',
],
'Chad' => [
'code' => 'td',
],
'Chile' => [
'code' => 'cl',
],
'China' => [
'code' => 'cn',
],
'Christmas Island' => [
'code' => 'cx',
],
'Cocos (keeling) Islands' => [
'code' => 'cc',
],
'Colombia' => [
'code' => 'co',
],
'Comoros' => [
'code' => 'km',
],
'Congo' => [
'code' => 'cg',
],
'Cook Islands' => [
'code' => 'ck',
],
'Costa Rica' => [
'code' => 'cr',
],
'Croatia' => [
'code' => 'hr',
],
'Cuba' => [
'code' => 'cu',
],
'Cyprus' => [
'code' => 'cy',
],
'Czech Republic' => [
'code' => 'cz',
],
'Denmark' => [
'code' => 'dk',
],
'Djibouti' => [
'code' => 'dj',
],
'Dominica' => [
'code' => 'dm',
],
'Dominican Republic' => [
'code' => 'do',
],
'East Timor' => [
'code' => 'tl',
],
'Ecuador' => [
'code' => 'ec',
],
'Egypt' => [
'code' => 'eg',
],
'El Salvador' => [
'code' => 'sv',
],
'Equatorial Guinea' => [
'code' => 'gq',
],
'Eritrea' => [
'code' => 'er',
],
'Estonia' => [
'code' => 'ee',
],
'Ethiopia' => [
'code' => 'et',
],
'Falkland Islands' => [
'code' => 'fk',
],
'Faroe Islands' => [
'code' => 'fo',
],
'Fiji Islands' => [
'code' => 'fj',
],
'Finland' => [
'code' => 'fi',
],
'France' => [
'code' => 'fr',
],
'French Guiana' => [
'code' => 'gf',
],
'French Polynesia' => [
'code' => 'pf',
],
'French Southern Territories' => [
'code' => 'tf',
],
'Gabon' => [
'code' => 'ga',
],
'Gambia' => [
'code' => 'gm',
],
'Georgia' => [
'code' => 'ge',
],
'Germany' => [
'code' => 'de',
],
'Ghana' => [
'code' => 'gh',
],
'Gibraltar' => [
'code' => 'gi',
],
'Greece' => [
'code' => 'gr',
],
'Greenland' => [
'code' => 'gl',
],
'Grenada' => [
'code' => 'gd',
],
'Guadeloupe' => [
'code' => 'gp',
],
'Guam' => [
'code' => 'gu',
],
'Guatemala' => [
'code' => 'gt',
],
'Guernsey' => [
'code' => 'gg',
],
'Guinea' => [
'code' => 'gn',
],
'Guinea Bissau' => [
'code' => 'gw',
],
'Guyana' => [
'code' => 'gy',
],
'Haiti' => [
'code' => 'ht',
],
'Heard Island And Mcdonald Islands' => [
'code' => 'hm',
],
'Holy See (vatican City State)' => [
'code' => 'va',
],
'Honduras' => [
'code' => 'hn',
],
'Hong Kong' => [
'code' => 'hk',
],
'Hungary' => [
'code' => 'hu',
],
'Iceland' => [
'code' => 'is',
],
'India' => [
'code' => 'in',
],
'Indonesia' => [
'code' => 'id',
],
'Iran' => [
'code' => 'ir',
],
'Iraq' => [
'code' => 'iq',
],
'Ireland' => [
'code' => 'ie',
],
'Isle Of Man' => [
'code' => 'im',
],
'Israel' => [
'code' => 'il',
],
'Italy' => [
'code' => 'it',
],
'Ivory Coast' => [
'code' => 'ci',
],
'Jamaica' => [
'code' => 'jm',
],
'Japan' => [
'code' => 'jp',
],
'Jersey' => [
'code' => 'je',
],
'Jordan' => [
'code' => 'jo',
],
'Kazakhstan' => [
'code' => 'kz',
],
'Kenya' => [
'code' => 'ke',
],
'Kiribati' => [
'code' => 'ki',
],
'Kuwait' => [
'code' => 'kw',
],
'Kyrgyzstan' => [
'code' => 'kg',
],
'Laos' => [
'code' => 'la',
],
'Latvia' => [
'code' => 'lv',
],
'Lebanon' => [
'code' => 'lb',
],
'Lesotho' => [
'code' => 'ls',
],
'Liberia' => [
'code' => 'lr',
],
'Libya' => [
'code' => 'ly',
],
'Liechtenstein' => [
'code' => 'li',
],
'Lithuania' => [
'code' => 'lt',
],
'Luxembourg' => [
'code' => 'lu',
],
'Macao' => [
'code' => 'mo',
],
'Madagascar' => [
'code' => 'mg',
],
'Malawi' => [
'code' => 'mw',
],
'Malaysia' => [
'code' => 'my',
],
'Maldives' => [
'code' => 'mv',
],
'Mali' => [
'code' => 'ml',
],
'Malta' => [
'code' => 'mt',
],
'Marshall Islands' => [
'code' => 'mh',
],
'Martinique' => [
'code' => 'mq',
],
'Mauritania' => [
'code' => 'mr',
],
'Mauritius' => [
'code' => 'mu',
],
'Mayotte' => [
'code' => 'yt',
],
'Mexico' => [
'code' => 'mx',
],
'Micronesia Federated States Of' => [
'code' => 'fm',
],
'Moldova' => [
'code' => 'md',
],
'Monaco' => [
'code' => 'mc',
],
'Mongolia' => [
'code' => 'mn',
],
'Montenegro' => [
'code' => 'me',
],
'Montserrat' => [
'code' => 'ms',
],
'Morocco' => [
'code' => 'ma',
],
'Mozambique' => [
'code' => 'mz',
],
'Myanmar' => [
'code' => 'mm',
],
'Namibia' => [
'code' => 'na',
],
'Nauru' => [
'code' => 'nr',
],
'Nepal' => [
'code' => 'np',
],
'Netherlands' => [
'code' => 'nl',
],
'New Caledonia' => [
'code' => 'nc',
],
'New Zealand' => [
'code' => 'nz',
],
'Nicaragua' => [
'code' => 'ni',
],
'Niger' => [
'code' => 'ne',
],
'Nigeria' => [
'code' => 'ng',
],
'Niue' => [
'code' => 'nu',
],
'Norfolk Island' => [
'code' => 'nf',
],
'North Korea' => [
'code' => 'kp',
],
'North Macedonia' => [
'code' => 'mk',
],
'Norway' => [
'code' => 'no',
],
'Oman' => [
'code' => 'om',
],
'Pakistan' => [
'code' => 'pk',
],
'Palau' => [
'code' => 'pw',
],
'Palestine' => [
'code' => 'ps',
],
'Panama' => [
'code' => 'pa',
],
'Papua New Guinea' => [
'code' => 'pg',
],
'Paraguay' => [
'code' => 'py',
],
'Peru' => [
'code' => 'pe',
],
'Philippines' => [
'code' => 'ph',
],
'Pitcairn' => [
'code' => 'pn',
],
'Poland' => [
'code' => 'pl',
],
'Portugal' => [
'code' => 'pt',
],
'Puerto Rico' => [
'code' => 'pr',
],
'Qatar' => [
'code' => 'qa',
],
'Quebec' => [
'code' => 'fr-ca',
],
'Reunion' => [
'code' => 're',
],
'Romania' => [
'code' => 'ro',
],
'Russian Federation' => [
'code' => 'ru',
],
'Rwanda' => [
'code' => 'rw',
],
'Saint Helena' => [
'code' => 'sh',
],
'Saint Kitts And Nevis' => [
'code' => 'kn',
],
'Saint Lucia' => [
'code' => 'lc',
],
'Saint Pierre And Miquelon' => [
'code' => 'pm',
],
'Saint Vincent And The Grenadines' => [
'code' => 'vc',
],
'Samoa' => [
'code' => 'ws',
],
'San Marino' => [
'code' => 'sm',
],
'Sao Tome And Principe' => [
'code' => 'st',
],
'Saudi Arabia' => [
'code' => 'sa',
],
'Senegal' => [
'code' => 'sn',
],
'Serbia' => [
'code' => 'rs',
],
'Seychelles' => [
'code' => 'sc',
],
'Sierra Leone' => [
'code' => 'sl',
],
'Singapore' => [
'code' => 'sg',
],
'Slovakia' => [
'code' => 'sk',
],
'Slovenia' => [
'code' => 'si',
],
'Solomon Islands' => [
'code' => 'sb',
],
'Somalia' => [
'code' => 'so',
],
'South Africa' => [
'code' => 'za',
],
'South Georgia And The South Sandwich Islands' => [
'code' => 'gs',
],
'South Korea' => [
'code' => 'kr',
],
'South Sudan' => [
'code' => 'ss',
],
'Spain' => [
'code' => 'es',
],
'Sri Lanka' => [
'code' => 'lk',
],
'Sudan' => [
'code' => 'sd',
],
'Suriname' => [
'code' => 'sr',
],
'Svalbard And Jan Mayen' => [
'code' => 'sj',
],
'Sweden' => [
'code' => 'se',
],
'Switzerland' => [
'code' => 'ch',
],
'Syria' => [
'code' => 'sy',
],
'Tajikistan' => [
'code' => 'tj',
],
'Tanzania' => [
'code' => 'tz',
],
'Thailand' => [
'code' => 'th',
],
'The Democratic Republic Of Congo' => [
'code' => 'cd',
],
'Togo' => [
'code' => 'tg',
],
'Tokelau' => [
'code' => 'tk',
],
'Tonga' => [
'code' => 'to',
],
'Trinidad And Tobago' => [
'code' => 'tt',
],
'Tunisia' => [
'code' => 'tn',
],
'Turkey' => [
'code' => 'tr',
],
'Turkmenistan' => [
'code' => 'tm',
],
'Turks And Caicos Islands' => [
'code' => 'tc',
],
'Tuvalu' => [
'code' => 'tv',
],
'Uganda' => [
'code' => 'ug',
],
'Ukraine' => [
'code' => 'ua',
],
'United Arab Emirates' => [
'code' => 'ae',
],
'United Kingdom' => [
'code' => 'gb',
],
'United States' => [
'code' => 'us',
],
'United States Minor Outlying Islands' => [
'code' => 'um',
],
'Uruguay' => [
'code' => 'uy',
],
'Uzbekistan' => [
'code' => 'uz',
],
'Vanuatu' => [
'code' => 'vu',
],
'Venezuela' => [
'code' => 've',
],
'Vietnam' => [
'code' => 'vn',
],
'Virgin Islands British' => [
'code' => 'vg',
],
'Virgin Islands Us' => [
'code' => 'vi',
],
'Wales' => [
'code' => 'gb-wls',
],
'Wallis And Futuna' => [
'code' => 'wf',
],
'Western Sahara' => [
'code' => 'eh',
],
'Yemen' => [
'code' => 'ye',
],
'Zambia' => [
'code' => 'zm',
],
'Zimbabwe' => [
'code' => 'zw',
]
];
}

View File

@@ -0,0 +1,759 @@
<?php
namespace Languages;
class Languages
{
public static $defaultLanguages = [
'af' => [
'code' => 'af',
'english' => "Afrikaans",
'local' => "Afrikaans",
'rtl' => false,
],
'am' => [
'code' => 'am',
'english' => "Amharic",
'local' => "አማርኛ",
'rtl' => false,
],
'ar' => [
'code' => 'ar',
'english' => "Arabic",
'local' => "العربية‏",
'rtl' => true,
],
'az' => [
'code' => 'az',
'english' => "Azerbaijani",
'local' => "Azərbaycan dili",
'rtl' => false,
],
'ba' => [
'code' => 'ba',
'english' => "Bashkir",
'local' => "башҡорт теле",
'rtl' => false,
],
'be' => [
'code' => 'be',
'english' => "Belarusian",
'local' => "Беларуская",
'rtl' => false,
],
'bg' => [
'code' => 'bg',
'english' => "Bulgarian",
'local' => "Български",
'rtl' => false,
],
'bn' => [
'code' => 'bn',
'english' => "Bengali",
'local' => "বাংলা",
'rtl' => false,
],
'br' => [
'code' => 'br',
'english' => "Brazilian Portuguese",
'local' => "Português Brasileiro",
'rtl' => false,
],
'bs' => [
'code' => 'bs',
'english' => "Bosnian",
'local' => "Bosanski",
'rtl' => false,
],
'ca' => [
'code' => 'ca',
'english' => "Catalan",
'local' => "Català",
'rtl' => false,
],
'co' => [
'code' => 'co',
'english' => "Corsican",
'local' => "Corsu",
'rtl' => false,
],
'cs' => [
'code' => 'cs',
'english' => "Czech",
'local' => "Čeština",
'rtl' => false,
],
'cy' => [
'code' => 'cy',
'english' => "Welsh",
'local' => "Cymraeg",
'rtl' => false,
],
'da' => [
'code' => 'da',
'english' => "Danish",
'local' => "Dansk",
'rtl' => false,
],
'de' => [
'code' => 'de',
'english' => "German",
'local' => "Deutsch",
'rtl' => false,
],
'el' => [
'code' => 'el',
'english' => "Greek",
'local' => "Ελληνικά",
'rtl' => false,
],
'en' => [
'code' => 'en',
'english' => "English",
'local' => "English",
'rtl' => false,
],
'eo' => [
'code' => 'eo',
'english' => "Esperanto",
'local' => "Esperanto",
'rtl' => false,
],
'es' => [
'code' => 'es',
'english' => "Spanish",
'local' => "Español",
'rtl' => false,
],
'et' => [
'code' => 'et',
'english' => "Estonian",
'local' => "Eesti",
'rtl' => false,
],
'eu' => [
'code' => 'eu',
'english' => "Basque",
'local' => "Euskara",
'rtl' => false,
],
'fa' => [
'code' => 'fa',
'english' => "Persian",
'local' => "فارسی",
'rtl' => true,
],
'fi' => [
'code' => 'fi',
'english' => "Finnish",
'local' => "Suomi",
'rtl' => false,
],
'fj' => [
'code' => 'fj',
'english' => "Fijian",
'local' => "Vosa Vakaviti",
'rtl' => false,
],
'fl' => [
'code' => 'fl',
'english' => "Filipino",
'local' => "Filipino",
'rtl' => false,
],
'fr' => [
'code' => 'fr',
'english' => "French",
'local' => "Français",
'rtl' => false,
],
'fy' => [
'code' => 'fy',
'english' => "Western Frisian",
'local' => "frysk",
'rtl' => false,
],
'ga' => [
'code' => 'ga',
'english' => "Irish",
'local' => "Gaeilge",
'rtl' => false,
],
'gd' => [
'code' => 'gd',
'english' => "Scottish Gaelic",
'local' => "Gàidhlig",
'rtl' => false,
],
'gl' => [
'code' => 'gl',
'english' => "Galician",
'local' => "Galego",
'rtl' => false,
],
'gu' => [
'code' => 'gu',
'english' => "Gujarati",
'local' => "ગુજરાતી",
'rtl' => false,
],
'ha' => [
'code' => 'ha',
'english' => "Hausa",
'local' => "هَوُسَ",
'rtl' => false,
],
'he' => [
'code' => 'he',
'english' => "Hebrew",
'local' => "עברית",
'rtl' => true,
],
'hi' => [
'code' => 'hi',
'english' => "Hindi",
'local' => "हिंदी",
'rtl' => false,
],
'hr' => [
'code' => 'hr',
'english' => "Croatian",
'local' => "Hrvatski",
'rtl' => false,
],
'ht' => [
'code' => 'ht',
'english' => "Haitian Creole",
'local' => "Kreyòl ayisyen",
'rtl' => false,
],
'hu' => [
'code' => 'hu',
'english' => "Hungarian",
'local' => "Magyar",
'rtl' => false,
],
'hw' => [
'code' => 'hw',
'english' => "Hawaiian",
'local' => "Ōlelo Hawaii",
'rtl' => false,
],
'hy' => [
'code' => 'hy',
'english' => "Armenian",
'local' => "հայերեն",
'rtl' => false,
],
'id' => [
'code' => 'id',
'english' => "Indonesian",
'local' => "Bahasa Indonesia",
'rtl' => false,
],
'ig' => [
'code' => 'ig',
'english' => "Igbo",
'local' => "Igbo",
'rtl' => false,
],
'is' => [
'code' => 'is',
'english' => "Icelandic",
'local' => "Íslenska",
'rtl' => false,
],
'it' => [
'code' => 'it',
'english' => "Italian",
'local' => "Italiano",
'rtl' => false,
],
'ja' => [
'code' => 'ja',
'english' => "Japanese",
'local' => "日本語",
'rtl' => false,
],
'jv' => [
'code' => 'jv',
'english' => "Javanese",
'local' => "Wong Jawa",
'rtl' => false,
],
'ka' => [
'code' => 'ka',
'english' => "Georgian",
'local' => "ქართული",
'rtl' => false,
],
'kk' => [
'code' => 'kk',
'english' => "Kazakh",
'local' => "Қазақша",
'rtl' => false,
],
'km' => [
'code' => 'km',
'english' => "Central Khmer",
'local' => "ភាសាខ្មែរ",
'rtl' => false,
],
'kn' => [
'code' => 'kn',
'english' => "Kannada",
'local' => "ಕನ್ನಡ",
'rtl' => false,
],
'ko' => [
'code' => 'ko',
'english' => "Korean",
'local' => "한국어",
'rtl' => false,
],
'ku' => [
'code' => 'ku',
'english' => "Kurdish",
'local' => "كوردی",
'rtl' => true,
],
'ky' => [
'code' => 'ky',
'english' => "Kyrgyz",
'local' => "кыргызча",
'rtl' => false,
],
'la' => [
'code' => 'la',
'english' => "Latin",
'local' => "Latine",
'rtl' => false,
],
'lb' => [
'code' => 'lb',
'english' => "Luxembourgish",
'local' => "Lëtzebuergesch",
'rtl' => false,
],
'lo' => [
'code' => 'lo',
'english' => "Lao",
'local' => "ພາສາລາວ",
'rtl' => false,
],
'lt' => [
'code' => 'lt',
'english' => "Lithuanian",
'local' => "Lietuvių",
'rtl' => false,
],
'lv' => [
'code' => 'lv',
'english' => "Latvian",
'local' => "Latviešu",
'rtl' => false,
],
'lg' => [
'code' => 'lg',
'english' => "Luganda",
'local' => "Oluganda",
'rtl' => false,
],
'mg' => [
'code' => 'mg',
'english' => "Malagasy",
'local' => "Malagasy",
'rtl' => false,
],
'mi' => [
'code' => 'mi',
'english' => "Māori",
'local' => "te reo Māori",
'rtl' => false,
],
'mk' => [
'code' => 'mk',
'english' => "Macedonian",
'local' => "Македонски",
'rtl' => false,
],
'ml' => [
'code' => 'ml',
'english' => "Malayalam",
'local' => "മലയാളം",
'rtl' => false,
],
'mn' => [
'code' => 'mn',
'english' => "Mongolian",
'local' => "Монгол",
'rtl' => false,
],
'mr' => [
'code' => 'mr',
'english' => "Marathi",
'local' => "मराठी",
'rtl' => false,
],
'ms' => [
'code' => 'ms',
'english' => "Malay",
'local' => "Bahasa Melayu",
'rtl' => false,
],
'mt' => [
'code' => 'mt',
'english' => "Maltese",
'local' => "Malti",
'rtl' => false,
],
'my' => [
'code' => 'my',
'english' => "Burmese",
'local' => "မျန္မာစာ",
'rtl' => false,
],
'ne' => [
'code' => 'ne',
'english' => "Nepali",
'local' => "नेपाली",
'rtl' => false,
],
'nl' => [
'code' => 'nl',
'english' => "Dutch",
'local' => "Nederlands",
'rtl' => false,
],
'no' => [
'code' => 'no',
'english' => "Norwegian",
'local' => "Norsk",
'rtl' => false,
],
'ny' => [
'code' => 'ny',
'english' => "Chichewa",
'local' => "chiCheŵa",
'rtl' => false,
],
'pa' => [
'code' => 'pa',
'english' => "Punjabi",
'local' => "ਪੰਜਾਬੀ",
'rtl' => false,
],
'pl' => [
'code' => 'pl',
'english' => "Polish",
'local' => "Polski",
'rtl' => false,
],
'ps' => [
'code' => 'ps',
'english' => "Pashto",
'local' => "پښت",
'rtl' => false,
],
'pt' => [
'code' => 'pt',
'english' => "Portuguese",
'local' => "Português",
'rtl' => false,
],
'ro' => [
'code' => 'ro',
'english' => "Romanian",
'local' => "Română",
'rtl' => false,
],
'ru' => [
'code' => 'ru',
'english' => "Russian",
'local' => "Русский",
'rtl' => false,
],
'sd' => [
'code' => 'sd',
'english' => "Sindhi",
'local' => "سنڌي، سندھی, सिन्धी",
'rtl' => false,
],
'si' => [
'code' => 'si',
'english' => "Sinhalese",
'local' => "සිංහල",
'rtl' => false,
],
'sk' => [
'code' => 'sk',
'english' => "Slovak",
'local' => "Slovenčina",
'rtl' => false,
],
'sl' => [
'code' => 'sl',
'english' => "Slovenian",
'local' => "Slovenščina",
'rtl' => false,
],
'sm' => [
'code' => 'sm',
'english' => "Samoan",
'local' => "gagana fa'a Samoa",
'rtl' => false,
],
'sn' => [
'code' => 'sn',
'english' => "Shona",
'local' => "chiShona",
'rtl' => false,
],
'so' => [
'code' => 'so',
'english' => "Somali",
'local' => "Soomaaliga",
'rtl' => false,
],
'sq' => [
'code' => 'sq',
'english' => "Albanian",
'local' => "Shqip",
'rtl' => false,
],
'sr' => [
'code' => 'sr',
'english' => "Serbian (Cyrillic)",
'local' => "Српски",
'rtl' => false,
],
'st' => [
'code' => 'st',
'english' => "Southern Sotho",
'local' => "seSotho",
'rtl' => false,
],
'su' => [
'code' => 'su',
'english' => "Sundanese",
'local' => "Sundanese",
'rtl' => false,
],
'sv' => [
'code' => 'sv',
'english' => "Swedish",
'local' => "Svenska",
'rtl' => false,
],
'sw' => [
'code' => 'sw',
'english' => "Swahili",
'local' => "Kiswahili",
'rtl' => false,
],
'ta' => [
'code' => 'ta',
'english' => "Tamil",
'local' => "தமிழ்",
'rtl' => false,
],
'te' => [
'code' => 'te',
'english' => "Telugu",
'local' => "తెలుగు",
'rtl' => false,
],
'tg' => [
'code' => 'tg',
'english' => "Tajik",
'local' => "Тоҷикӣ",
'rtl' => false,
],
'th' => [
'code' => 'th',
'english' => "Thai",
'local' => "ภาษาไทย",
'rtl' => false,
],
'tl' => [
'code' => 'tl',
'english' => "Tagalog",
'local' => "Tagalog",
'rtl' => false,
],
'to' => [
'code' => 'to',
'english' => "Tongan",
'local' => "faka-Tonga",
'rtl' => false,
],
'tr' => [
'code' => 'tr',
'english' => "Turkish",
'local' => "Türkçe",
'rtl' => false,
],
'tt' => [
'code' => 'tt',
'english' => "Tatar",
'local' => "Tatar",
'rtl' => false,
],
'tw' => [
'code' => 'tw',
'english' => "Traditional Chinese",
'local' => "中文 (繁體)",
'rtl' => false,
],
'ty' => [
'code' => 'ty',
'english' => "Tahitian",
'local' => "te reo Tahiti, te reo Māʼohi",
'rtl' => false,
],
'uk' => [
'code' => 'uk',
'english' => "Ukrainian",
'local' => "Українська",
'rtl' => false,
],
'ur' => [
'code' => 'ur',
'english' => "Urdu",
'local' => "اردو",
'rtl' => true,
],
'uz' => [
'code' => 'uz',
'english' => "Uzbek",
'local' => "O'zbek",
'rtl' => false,
],
'vi' => [
'code' => 'vi',
'english' => "Vietnamese",
'local' => "Tiếng Việt",
'rtl' => false,
],
'xh' => [
'code' => 'xh',
'english' => "Xhosa",
'local' => "isiXhosa",
'rtl' => false,
],
'yi' => [
'code' => 'yi',
'english' => "Yiddish",
'local' => "ייִדיש",
'rtl' => false,
],
'yo' => [
'code' => 'yo',
'english' => "Yoruba",
'local' => "Yorùbá",
'rtl' => false,
],
'zh' => [
'code' => 'zh',
'english' => "Simplified Chinese",
'local' => "中文 (简体)",
'rtl' => false,
],
'zu' => [
'code' => 'zu',
'english' => "Zulu",
'local' => "isiZulu",
'rtl' => false,
],
'hm' => [
'code' => 'hm',
'english' => "Hmong",
'local' => "Hmoob",
'rtl' => false,
],
'cb' => [
'code' => 'cb',
'english' => "Cebuano",
'local' => "Sugbuanon",
'rtl' => false,
],
'or' => [
'code' => 'or',
'english' => "Odia",
'local' => "ଓଡ଼ିଆ",
'rtl' => false,
],
'tk' => [
'code' => 'tk',
'english' => "Turkmen",
'local' => "Türkmen",
'rtl' => false,
],
'ug' => [
'code' => 'ug',
'english' => "Uyghur",
'local' => "ئۇيغۇر",
'rtl' => true,
],
'fc' => [
'code' => 'fc',
'english' => "French (Canada)",
'local' => "Français (Canada)",
'rtl' => false,
],
'as' => [
'code' => 'as',
'english' => "Assamese",
'local' => "অসমীয়া",
'rtl' => false,
],
'sa' => [
'code' => 'sa',
'english' => "Serbian (Latin)",
'local' => "Srpski",
'rtl' => false,
],
'om' => [
'code' => 'om',
'english' => "Oromo",
'local' => "Afaan Oromoo",
'rtl' => false,
],
'iu' => [
'code' => 'iu',
'english' => "Inuktitut",
'local' => "ᐃᓄᒃᑎᑐᑦ",
'rtl' => false,
],
'ti' => [
'code' => 'ti',
'english' => "Tigrinya",
'local' => "ቲግሪንያ",
'rtl' => false,
],
'bm' => [
'code' => 'bm',
'english' => "Bambara",
'local' => "Bamanankan",
'rtl' => false,
],
'bo' => [
'code' => 'bo',
'english' => "Tibetan",
'local' => "བོད་ཡིག",
'rtl' => false,
],
'ak' => [
'code' => 'ak',
'english' => "Akan",
'local' => "Baoulé",
'rtl' => false,
],
'rw' => [
'code' => 'rw',
'english' => "Kinyarwanda",
'local' => "Kinyarwanda",
'rtl' => false,
]
];
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,2 @@
import { languages } from "./data/languages.json";
export { languages };

View File

@@ -0,0 +1,2 @@
const { languages } = require("./data/languages.json");
module.exports = { languages };

View File

@@ -0,0 +1,30 @@
{
"name": "@weglot/languages",
"description": "Weglot Languages provides a set languages data and classes allowing you to easily use multiples flags as images",
"main": "index.js",
"module": "index.esm.js",
"license": "UNLICENSED",
"publishConfig": {
"registry": "https://npm.pkg.github.com/"
},
"scripts": {
"build": "npm run sass-compiler && npm run populate-languages && npm run build-svg",
"sass-compiler": "./node_modules/.bin/node-sass --importer node_modules/node-sass-json-importer/dist/cli.js --recursive ./assets/scss/styles.scss --output ./dist --output-style compressed --source-map true",
"flags-downloads": "cp -a ./node_modules/flag-icon-css/flags/. ./images/flag-icon-css/",
"populate-languages": "node bin/populateLanguages.js",
"build-svg": "node bin/buildSvg.js",
"test": "jest"
},
"repository": {
"type": "git",
"url": "git@github.com:weglot/languages.git"
},
"homepage": "https://github.com/weglot/languages#readme",
"devDependencies": {
"flag-icon-css": "^3.5.0",
"jest": "^29.6.1",
"node-sass": "^9.0.0",
"node-sass-json-importer": "^4.3.0"
},
"version": "1.61.1"
}

View File

@@ -0,0 +1,22 @@
<?php
namespace Weglot\Client\Api\Enum;
/**
* Enum BotType
* Used to define which bot is parsing the page.
* Basically, most of time we recommend to use as "human"
*
* @package Weglot\Client\Api\Enum
*/
abstract class BotType
{
const HUMAN = 0;
const OTHER = 1;
const GOOGLE = 2;
const BING = 3;
const YAHOO = 4;
const BAIDU = 5;
const YANDEX = 6;
const WGVE = 7;
}

View File

@@ -0,0 +1,31 @@
<?php
namespace Weglot\Client\Api\Enum;
/**
* Enum WordType
* Used to define where was the text we are parsing
*
* @package Weglot\Client\Api\Enum
*/
abstract class WordType
{
const OTHER = 0;
const TEXT = 1;
const VALUE = 2;
const PLACEHOLDER = 3;
const META_CONTENT = 4;
const IFRAME_SRC = 5;
const IMG_SRC = 6;
const IMG_ALT = 7;
const PDF_HREF = 8;
const TITLE = 9;
const EXTERNAL_LINK = 10;
/**
* Only for internal use, if you have to add a value in this enum,
* please increments the __MAX value.
*/
const __MIN = 0;
const __MAX = 10;
}

View File

@@ -0,0 +1,52 @@
<?php
namespace Weglot\Client\Api\Exception;
use Exception;
/**
* Class AbstractException
* @package Weglot\Client\Api\Exception
*/
abstract class AbstractException extends Exception
{
/**
* @var int
*/
protected $weglotCode;
/**
* @var array
*/
protected $jsonBody;
/**
* AbstractException constructor.
* @param string $message
* @param int $weglotCode
* @param array $jsonBody
*/
public function __construct($message, $weglotCode = WeglotCode::GENERIC, $jsonBody = [])
{
parent::__construct($message);
$this->weglotCode = $weglotCode;
$this->jsonBody = $jsonBody;
}
/**
* @return int
*/
public function getWeglotCode()
{
return $this->weglotCode;
}
/**
* @return array
*/
public function getJsonBody()
{
return $this->jsonBody;
}
}

View File

@@ -0,0 +1,20 @@
<?php
namespace Weglot\Client\Api\Exception;
/**
* Class ApiError
* @package Weglot\Client\Api\Exception
*/
class ApiError extends AbstractException
{
/**
* ApiError constructor.
* @param $message
* @param array $jsonBody
*/
public function __construct($message, array $jsonBody = [])
{
parent::__construct($message, WeglotCode::AUTH, $jsonBody);
}
}

View File

@@ -0,0 +1,23 @@
<?php
namespace Weglot\Client\Api\Exception;
/**
* Class InputAndOutputCountMatchException
* @package Weglot\Client\Api\Exception
*/
class InputAndOutputCountMatchException extends AbstractException
{
/**
* InputAndOutputCountMatchException constructor.
* @param array $jsonBody
*/
public function __construct(array $jsonBody)
{
parent::__construct(
'Input and ouput words count doesn\'t match.',
WeglotCode::PARAMETERS,
$jsonBody
);
}
}

View File

@@ -0,0 +1,21 @@
<?php
namespace Weglot\Client\Api\Exception;
/**
* Class InvalidLanguageException
* @package Weglot\Client\Api\Exception
*/
class InvalidLanguageException extends AbstractException
{
/**
* InvalidLanguageException constructor.
*/
public function __construct()
{
parent::__construct(
'The given language is invalid.',
WeglotCode::PARAMETERS
);
}
}

View File

@@ -0,0 +1,21 @@
<?php
namespace Weglot\Client\Api\Exception;
/**
* Class InvalidWordTypeException
* @package Weglot\Client\Api\Exception
*/
class InvalidWordTypeException extends AbstractException
{
/**
* InvalidWordTypeException constructor.
*/
public function __construct()
{
parent::__construct(
'The given WordType is invalid.',
WeglotCode::PARAMETERS
);
}
}

View File

@@ -0,0 +1,21 @@
<?php
namespace Weglot\Client\Api\Exception;
/**
* Class MissingRequiredParamException
* @package Weglot\Client\Api\Exception
*/
class MissingRequiredParamException extends AbstractException
{
/**
* MissingRequiredParamException constructor.
*/
public function __construct()
{
parent::__construct(
'Required fields for $params are: language_from, language_to, bot, request_url.',
WeglotCode::PARAMETERS
);
}
}

View File

@@ -0,0 +1,23 @@
<?php
namespace Weglot\Client\Api\Exception;
/**
* Class MissingWordsOutputException
* @package Weglot\Client\Api\Exception
*/
class MissingWordsOutputException extends \Exception
{
/**
* MissingWordsOutputException constructor.
* @param array $jsonBody
*/
public function __construct(array $jsonBody)
{
parent::__construct(
'There is no output words.',
WeglotCode::GENERIC,
$jsonBody
);
}
}

View File

@@ -0,0 +1,14 @@
<?php
namespace Weglot\Client\Api\Exception;
/**
* Class WeglotCode
* @package Weglot\Client\Api\Exception
*/
abstract class WeglotCode
{
const GENERIC = 0;
const AUTH = 1;
const PARAMETERS = 2;
}

View File

@@ -0,0 +1,37 @@
<?php
namespace Weglot\Client\Api;
use Weglot\Client\Api\Shared\AbstractCollection;
use Weglot\Client\Api\Shared\AbstractCollectionEntry;
/**
* Class LanguageCollection
* @package Weglot\Client\Api
*/
class LanguageCollection extends AbstractCollection
{
/**
* @param AbstractCollectionEntry $entry
* @return $this
*/
public function addOne(AbstractCollectionEntry $entry)
{
$this->collection[$entry->getInternalCode()] = $entry;
return $this;
}
/**
* @param string $iso639 ISO 639-1 code to identify language
*
* @return AbstractCollectionEntry|null
*/
public function getCode($iso639)
{
if (isset($this[$iso639])) {
return $this[$iso639];
}
return null;
}
}

View File

@@ -0,0 +1,172 @@
<?php
namespace Weglot\Client\Api;
use Weglot\Client\Api\Shared\AbstractCollectionEntry;
/**
* Class LanguageEntry
* @package Weglot\Client\Api
*/
class LanguageEntry extends AbstractCollectionEntry
{
/**
* Internal weglot code to identify language, is 2 letters, eg tw
*
* @var string
*/
protected $internalCode;
/**
* External code that shows on website on URLs (can be more than 2 letters)
*
* @var string
*/
protected $externalCode;
/**
* English name of the language
*
* @var string
*/
protected $englishName;
/**
* Name of the language in the language
*
* @var string
*/
protected $localName;
/**
* Language is right to left
*
* @var bool
*/
protected $isRtl;
/**
* LanguageEntry constructor.
* @param string $internalCode Internal weglot code to identify language
* @param string $externalCode External code that shows on website on URLs
* @param string $englishName English name of the language
* @param string $localName Name of the language in the language
* @param bool $isRtl Language is right to left
*/
public function __construct($internalCode, $externalCode, $englishName, $localName, $isRtl = false)
{
$this
->setInternalCode($internalCode)
->setExternalCode($externalCode)
->setEnglishName($englishName)
->setLocalName($localName)
->setRtl($isRtl);
}
/**
* @param $internalCode
* @return $this
*/
public function setInternalCode($internalCode)
{
$this->internalCode = $internalCode;
return $this;
}
/**
* @return string
*/
public function getInternalCode()
{
return $this->internalCode;
}
/**
* @param $externalCode
* @return $this
*/
public function setExternalCode($externalCode)
{
$this->externalCode = isset($externalCode) ? $externalCode : $this->internalCode;
return $this;
}
/**
* @return string
*/
public function getExternalCode()
{
return $this->externalCode;
}
/**
* @param string $englishName
* @return $this
*/
public function setEnglishName($englishName)
{
$this->englishName = $englishName;
return $this;
}
/**
* @return string
*/
public function getEnglishName()
{
return $this->englishName;
}
/**
* @param $localName
* @return $this
*/
public function setLocalName($localName)
{
$this->localName = $localName;
return $this;
}
/**
* @return string
*/
public function getLocalName()
{
return $this->localName;
}
/**
* @param bool $rtl
* @return $this
*/
public function setRtl($rtl)
{
$this->isRtl = $rtl;
return $this;
}
/**
* @return bool
*/
public function isRtl()
{
return $this->isRtl;
}
#[\ReturnTypeWillChange]
public function jsonSerialize()
{
return [
'internal_code' => $this->getInternalCode(),
'external_code' => $this->getExternalCode(),
'english' => $this->getEnglishName(),
'local' => $this->getLocalName(),
'rtl' => $this->isRtl(),
];
}
}

View File

@@ -0,0 +1,49 @@
<?php
namespace Weglot\Client\Api\Shared;
use Countable;
use Iterator;
use ArrayAccess;
use JsonSerializable;
/**
* Class AbstractCollection
* @package Weglot\Client\Api\Shared
*/
abstract class AbstractCollection implements Countable, Iterator, ArrayAccess, JsonSerializable, AbstractCollectionInterface
{
use AbstractCollectionCountable;
use AbstractCollectionArrayAccess;
use AbstractCollectionSerializable;
use AbstractCollectionIterator;
/**
* @var AbstractCollectionEntry[]
*/
protected $collection = [];
/**
* @param AbstractCollectionEntry $entry
* @return $this
*/
public function addOne(AbstractCollectionEntry $entry)
{
$this->collection[] = $entry;
return $this;
}
/**
* @param array $entries
* @return $this
*/
public function addMany(array $entries)
{
foreach ($entries as $entry) {
$this->addOne($entry);
}
return $this;
}
}

View File

@@ -0,0 +1,47 @@
<?php
namespace Weglot\Client\Api\Shared;
/**
* Trait AbstractCollectionArrayAccess
* @package Weglot\Client\Api\Shared
*/
trait AbstractCollectionArrayAccess
{
/**
* {@inheritdoc}
*/
#[\ReturnTypeWillChange]
public function offsetExists($offset) {
return isset($this->collection[$offset]);
}
/**
* {@inheritdoc}
*/
#[\ReturnTypeWillChange]
public function offsetGet($offset)
{
return isset($this->collection[$offset]) ? $this->collection[$offset] : null;
}
/**
* {@inheritdoc}
*/
#[\ReturnTypeWillChange]
public function offsetSet($offset, $value)
{
if (isset($this->collection[$offset]) && $value instanceof AbstractCollectionEntry) {
$this->collection[$offset] = $value;
}
}
/**
* {@inheritdoc}
*/
#[\ReturnTypeWillChange]
public function offsetUnset($offset)
{
unset($this->collection[$offset]);
}
}

View File

@@ -0,0 +1,18 @@
<?php
namespace Weglot\Client\Api\Shared;
/**
* Trait AbstractCollectionCountable
* @package Weglot\Client\Api\Shared
*/
trait AbstractCollectionCountable
{
/**
* {@inheritdoc}
*/
#[\ReturnTypeWillChange]
public function count() {
return \count($this->collection);
}
}

View File

@@ -0,0 +1,13 @@
<?php
namespace Weglot\Client\Api\Shared;
use JsonSerializable;
/**
* Class AbstractCollectionEntry
* @package Weglot\Client\Api\Shared
*/
abstract class AbstractCollectionEntry implements JsonSerializable
{
}

View File

@@ -0,0 +1,24 @@
<?php
namespace Weglot\Client\Api\Shared;
/**
* Interface AbstractCollectionInterface
* @package Weglot\Client\Api\Shared
*/
interface AbstractCollectionInterface
{
/**
* Add one word at a time
*
* @param AbstractCollectionEntry $entry
*/
public function addOne(AbstractCollectionEntry $entry);
/**
* Add several words at once
*
* @param AbstractCollectionEntry[] $entries
*/
public function addMany(array $entries);
}

View File

@@ -0,0 +1,55 @@
<?php
namespace Weglot\Client\Api\Shared;
/**
* Trait AbstractCollectionSerializable
* @package Weglot\Client\Api\Shared
*/
trait AbstractCollectionIterator
{
/**
* {@inheritdoc}
*/
#[\ReturnTypeWillChange]
public function current()
{
return current($this->collection);
}
/**
* {@inheritdoc}
*/
#[\ReturnTypeWillChange]
public function next()
{
return next($this->collection);
}
/**
* {@inheritdoc}
*/
#[\ReturnTypeWillChange]
public function key()
{
return key($this->collection);
}
/**
* {@inheritdoc}
*/
#[\ReturnTypeWillChange]
public function valid()
{
return key($this->collection) !== null;
}
/**
* {@inheritdoc}
*/
#[\ReturnTypeWillChange]
public function rewind()
{
return reset($this->collection);
}
}

View File

@@ -0,0 +1,24 @@
<?php
namespace Weglot\Client\Api\Shared;
/**
* Trait AbstractCollectionSerializable
* @package Weglot\Client\Api\Shared
*/
trait AbstractCollectionSerializable
{
/**
* {@inheritdoc}
*/
#[\ReturnTypeWillChange]
public function jsonSerialize()
{
$words = [];
foreach ($this->collection as $entry) {
$words[] = $entry->jsonSerialize();
}
return $words;
}
}

View File

@@ -0,0 +1,183 @@
<?php
namespace Weglot\Client\Api;
use JsonSerializable;
use Weglot\Client\Api\Exception\MissingRequiredParamException;
if (!function_exists('array_keys_exists')) {
/**
* Used to check if multiple keys are defined in given array
*
* @param array $keys
* @param array $arr
* @return bool
*/
function array_keys_exists(array $keys, array $arr)
{
return !array_diff_key(array_flip($keys), $arr);
}
}
/**
* Class TranslateEntry
* @package Weglot\Client\Api
*/
class TranslateEntry implements JsonSerializable
{
/**
* @var array
*/
protected $params;
/**
* @var WordCollection
*/
protected $inputWords;
/**
* @var WordCollection
*/
protected $outputWords;
/**
* TranslateEntry constructor.
* @param array $params Params of the translate entry, required fields: language_from, language_to, bot, request_url & optional: title ("Empty title" by default)
* @param WordCollection|null $words Collection of words
* @throws MissingRequiredParamException If params are missing we throw this exception
*/
public function __construct(array $params, WordCollection $words = null)
{
$this->setParams($params)
->setInputWords($words)
->setOutputWords();
}
/**
* Default params values
*
* @return array
*/
protected function defaultParams()
{
return [
'title' => 'Empty title'
];
}
/**
* Required params field names
*
* @return array
*/
protected function requiredParams()
{
return [
'language_from',
'language_to',
'bot',
'request_url'
];
}
/**
* @param null|string $key
* @return array|bool|mixed
*/
public function getParams($key = null)
{
if ($key !== null) {
if (isset($this->params[$key])) {
return $this->params[$key];
}
return false;
}
return $this->params;
}
/**
* @param array $params
* @return $this
* @throws MissingRequiredParamException If params are missing we throw this exception
*/
public function setParams(array $params)
{
// merging default params with user params
$this->params = array_merge($this->defaultParams(), $params);
if (!array_keys_exists($this->requiredParams(), $this->params)) {
throw new MissingRequiredParamException();
}
return $this;
}
/**
* @return WordCollection
*/
public function getInputWords()
{
return $this->inputWords;
}
/**
* Used to fill input words collection
* If $words is null, it would put an empty word collection
*
* @param WordCollection|null $words
* @return $this
*/
public function setInputWords($words = null)
{
if ($words === null) {
$this->inputWords = new WordCollection();
} else {
$this->inputWords = $words;
}
return $this;
}
/**
* @return WordCollection
*/
public function getOutputWords()
{
return $this->outputWords;
}
/**
* Used to fill output words collection
* If $words is null, it would put an empty word collection
*
* @param WordCollection|null $words
* @return $this
*/
public function setOutputWords($words = null)
{
if ($words === null) {
$this->outputWords = new WordCollection();
} else {
$this->outputWords = $words;
}
return $this;
}
/**
* {@inheritdoc}
*/
#[\ReturnTypeWillChange]
public function jsonSerialize()
{
return [
'l_from' => $this->params['language_from'],
'l_to' => $this->params['language_to'],
'bot' => $this->params['bot'],
'title' => $this->params['title'],
'request_url' => $this->params['request_url'],
'words' => $this->inputWords->jsonSerialize()
];
}
}

View File

@@ -0,0 +1,13 @@
<?php
namespace Weglot\Client\Api;
use Weglot\Client\Api\Shared\AbstractCollection;
/**
* Class WordCollection
* @package Weglot\Client\Api
*/
class WordCollection extends AbstractCollection
{
}

View File

@@ -0,0 +1,100 @@
<?php
namespace Weglot\Client\Api;
use Weglot\Client\Api\Enum\WordType;
use Weglot\Client\Api\Exception\InvalidWordTypeException;
use Weglot\Client\Api\Shared\AbstractCollectionEntry;
/**
* Class WordEntry
* @package Weglot\Client\Api
*/
class WordEntry extends AbstractCollectionEntry
{
/**
* @var string
*/
protected $word;
/**
* @var int
*/
protected $type = WordType::TEXT;
/**
* WordEntry constructor.
* @param $word
* @param int $type
* @throws InvalidWordTypeException
*/
public function __construct($word, $type = WordType::TEXT)
{
$this->setWord($word)
->setType($type);
}
/**
* @param string $word
* @return $this
*/
public function setWord($word)
{
$this->word = $word;
return $this;
}
/**
* @return string
*/
public function getWord()
{
return $this->word;
}
/**
* Set type of word you gonna translate.
* Returns false if type is incorrect.
*
* @param $type
* @return $this
* @throws InvalidWordTypeException
*/
public function setType($type)
{
/**
* Thoses WordType::__MIN and WordType::__MAX values are
* only used to check if given type is okay according to
* what we have in WordType.
*
* @see src/Client/Api/Enum/WordType.php
*/
if (!($type >= WordType::__MIN && $type <= WordType::__MAX)) {
throw new InvalidWordTypeException();
}
$this->type = $type;
return $this;
}
/**
* @return int
*/
#[\ReturnTypeWillChange]
public function getType() {
return $this->type;
}
/**
* {@inheritdoc}
*/
#[\ReturnTypeWillChange]
public function jsonSerialize()
{
return [
't' => $this->getType(),
'w' => $this->getWord()
];
}
}

View File

@@ -0,0 +1,119 @@
<?php
namespace Weglot\Client\Caching;
use Psr\Cache\CacheItemInterface;
use Psr\Cache\CacheItemPoolInterface;
use Psr\Cache\InvalidArgumentException;
/**
* Class Cache
* @package Weglot\Client\Caching\Cache
*/
class Cache implements CacheInterface
{
/**
* @var CacheItemPoolInterface|null
*/
protected $itemPool = null;
/**
* @var int
*/
protected $expire = 604800; // 7 days (= 60 * 60 * 24 * 7)
/**
* Cache constructor.
* @param null $itemPool
*/
public function __construct($itemPool = null)
{
$this->setItemPool($itemPool);
}
/**
* @param null|CacheItemPoolInterface $itemPool
* @return $this
*/
public function setItemPool($itemPool)
{
$this->itemPool = $itemPool;
return $this;
}
/**
* @return null|CacheItemPoolInterface
*/
public function getItemPool()
{
return $this->itemPool;
}
/**
* @param int $expire
* @return $this
*/
public function setExpire($expire)
{
$this->expire = $expire;
return $this;
}
/**
* @return int
*/
public function getExpire()
{
return $this->expire;
}
/**
* @return bool
*/
public function enabled()
{
return $this->itemPool !== null;
}
/**
* @param array $data
* @return string
*/
public function generateKey(array $data)
{
return 'wg_' .sha1(json_encode($data));
}
/**
* @param string $key
* @return CacheItemInterface
* @throws InvalidArgumentException
*/
public function get($key)
{
return $this->getItemPool()->getItem($key);
}
/**
* @param array $data
* @return CacheItemInterface
* @throws InvalidArgumentException
*/
public function getWithGenerate(array $data)
{
$key = $this->generateKey($data);
return $this->get($key);
}
/**
* @param CacheItemInterface $item
* @return bool
*/
public function save(CacheItemInterface $item)
{
$item->expiresAfter($this->getExpire());
return $this->getItemPool()->save($item);
}
}

View File

@@ -0,0 +1,70 @@
<?php
namespace Weglot\Client\Caching;
use Psr\Cache\CacheItemInterface;
use Psr\Cache\CacheItemPoolInterface;
/**
* Interface CacheInterface
* @package Weglot\Client\Caching
*/
interface CacheInterface
{
/**
* @param null|CacheItemPoolInterface $cacheItemPool
* @return $this
*/
public function setItemPool($cacheItemPool);
/**
* @return CacheItemPoolInterface
*/
public function getItemPool();
/**
* @param int $cacheExpire Time in seconds before expire, default is 86400
* @return $this
*/
public function setExpire($cacheExpire);
/**
* @return int
*/
public function getExpire();
/**
* Check if cache is enabled
*
* @return bool
*/
public function enabled();
/**
* Generate cache key based on sha1 hash
*
* @param array $array Body content of the request as array
* @return string
*/
public function generateKey(array $array);
/**
* @param string $key
* @return CacheItemInterface
*/
public function get($key);
/**
* Mix of generateKey & get functions
*
* @param array $data
* @return CacheItemInterface
*/
public function getWithGenerate(array $data);
/**
* @param CacheItemInterface $item
* @return bool
*/
public function save(CacheItemInterface $item);
}

View File

@@ -0,0 +1,240 @@
<?php
namespace Weglot\Client;
use GuzzleHttp\Exception\GuzzleException;
use Psr\Cache\CacheItemPoolInterface;
use Psr\Http\Message\ResponseInterface;
use Weglot\Client\Api\Exception\ApiError;
use Weglot\Client\Caching\Cache;
use Weglot\Client\Caching\CacheInterface;
use Weglot\Client\HttpClient\ClientInterface;
use Weglot\Client\HttpClient\CurlClient;
/**
* Class Client
* @package Weglot\Client
*/
class Client
{
/**
* Library version
*
* @var string
*/
const VERSION = '0.5.11';
/**
* Weglot API Key
*
* @var string
*/
protected $apiKey;
/**
* Weglot settings file Version
*
* @var string
*/
protected $version;
/**
* Options for client
*
* @var array
*/
protected $options;
/**
* Http Client
*
* @var ClientInterface
*/
protected $httpClient;
/**
* @var Profile
*/
protected $profile;
/**
* @var CacheInterface
*/
protected $cache;
/**
* Client constructor.
* @param string $apiKey your Weglot API key
* @param int $translationEngine
* @param string $version your settings file version
* @param array $options an array of options, currently only "host" is implemented
*/
public function __construct($apiKey, $translationEngine, $version = '1', $options = [])
{
$this->apiKey = $apiKey;
$this->version = $version;
$this->profile = new Profile($apiKey, $translationEngine);
$this
->setHttpClient()
->setOptions($options)
->setCache();
}
/**
* Creating Guzzle HTTP connector based on $options
*/
protected function setupConnector()
{
$this->httpClient = new CurlClient();
}
/**
* Default options values
*
* @return array
*/
public function defaultOptions()
{
return [
'host' => 'https://api.weglot.com'
];
}
/**
* @return array
*/
public function getOptions()
{
return $this->options;
}
/**
* @param array $options
* @return $this
*/
public function setOptions($options)
{
// merging default options with user options
$this->options = array_merge($this->defaultOptions(), $options);
return $this;
}
/**
* @param null|ClientInterface $httpClient
* @param null|string $customHeader
* @return $this
*/
public function setHttpClient($httpClient = null, $customHeader = null)
{
if ($httpClient === null) {
$httpClient = new CurlClient();
$header = 'Weglot-Context: PHP\\'.self::VERSION;
if (!is_null($customHeader)) {
$header .= ' ' .$customHeader;
}
$httpClient->addHeader($header);
}
if ($httpClient instanceof ClientInterface) {
$this->httpClient = $httpClient;
}
return $this;
}
/**
* @return ClientInterface
*/
public function getHttpClient()
{
return $this->httpClient;
}
/**
* @return Profile
*/
public function getProfile()
{
return $this->profile;
}
/**
* @param null|CacheInterface $cache
* @return $this
*/
public function setCache($cache = null)
{
if ($cache === null || !($cache instanceof CacheInterface)) {
$cache = new Cache();
}
$this->cache = $cache;
return $this;
}
/**
* @return CacheInterface
*/
public function getCache()
{
return $this->cache;
}
/**
* @param null|CacheItemPoolInterface $cacheItemPool
* @return $this
*/
public function setCacheItemPool($cacheItemPool)
{
$this->getCache()->setItemPool($cacheItemPool);
return $this;
}
/**
* Make the API call and return the response.
*
* @param string $method Method to use for given endpoint
* @param string $endpoint Endpoint to hit on API
* @param array $body Body content of the request as array
* @param bool $asArray To know if we return an array or ResponseInterface
* @return array|ResponseInterface
* @throws ApiError
*/
public function makeRequest($method, $endpoint, $body = [], $asArray = true)
{
try {
if($method === 'GET') {
$urlParams = array_merge( ['api_key' => $this->apiKey, 'v' => $this->version], $body);
$body = [];
}
else {
$urlParams = ['api_key' => $this->apiKey, 'v' => $this->version];
}
list($rawBody, $httpStatusCode, $httpHeader) = $this->getHttpClient()->request(
$method,
$this->makeAbsUrl($endpoint),
$urlParams,
$body
);
$array = json_decode($rawBody, true);
} catch (\Exception $e) {
throw new ApiError($e->getMessage(), $body);
}
if ($asArray) {
return $array;
}
return [$rawBody, $httpStatusCode, $httpHeader];
}
/**
* @param string $endpoint
* @return string
*/
protected function makeAbsUrl($endpoint)
{
return $this->options['host'] . $endpoint;
}
}

View File

@@ -0,0 +1,88 @@
<?php
namespace Weglot\Client\Endpoint;
use Weglot\Client\Api\Exception\ApiError;
use Weglot\Client\Api\Exception\InputAndOutputCountMatchException;
use Weglot\Client\Api\Exception\InvalidWordTypeException;
use Weglot\Client\Api\Exception\MissingRequiredParamException;
use Weglot\Client\Api\Exception\MissingWordsOutputException;
use Weglot\Client\Api\TranslateEntry;
use Weglot\Client\Client;
use Weglot\Client\Factory\Translate as TranslateFactory;
/**
* Class Translate
* @package Weglot\Client\Endpoint
*/
class CdnTranslate extends Endpoint
{
const METHOD = 'POST';
const ENDPOINT = '/translate';
/**
* @var TranslateEntry
*/
protected $translateEntry;
/**
* Translate constructor.
* @param TranslateEntry $translateEntry
* @param Client $client
*/
public function __construct(TranslateEntry $translateEntry, Client $client)
{
$this->setTranslateEntry($translateEntry);
$currentHost = $client->getOptions()['host'];
if($currentHost) {
$cdnHost = str_replace('https://api.weglot.' , 'https://cdn-api-weglot.' , $currentHost);
$client->setOptions(array('host' => $cdnHost ));
}
parent::__construct($client);
}
/**
* @return TranslateEntry
*/
public function getTranslateEntry()
{
return $this->translateEntry;
}
/**
* @param TranslateEntry $translateEntry
* @return $this
*/
public function setTranslateEntry(TranslateEntry $translateEntry)
{
$this->translateEntry = $translateEntry;
return $this;
}
/**
* @return TranslateEntry
* @throws ApiError
* @throws InputAndOutputCountMatchException
* @throws InvalidWordTypeException
* @throws MissingRequiredParamException
* @throws MissingWordsOutputException
*/
public function handle()
{
$asArray = $this->translateEntry->jsonSerialize();
if (!empty($asArray['words'])) {
list($rawBody, $httpStatusCode) = $this->request($asArray, false);
if ($httpStatusCode !== 200) {
throw new ApiError($rawBody, $asArray);
}
$response = json_decode($rawBody, true);
}
else {
throw new ApiError("Empty words passed", $asArray);
}
$factory = new TranslateFactory($response);
return $factory->handle();
}
}

View File

@@ -0,0 +1,87 @@
<?php
namespace Weglot\Client\Endpoint;
use Psr\Http\Message\ResponseInterface;
use Weglot\Client\Api\Exception\ApiError;
use Weglot\Client\Caching\CacheInterface;
use Weglot\Client\Client;
use Weglot\Client\Caching\Cache;
/**
* Class Endpoint
* @package Weglot\Client\Endpoint
*/
abstract class Endpoint
{
const METHOD = 'GET';
const ENDPOINT = '/';
/**
* @var Client
*/
protected $client;
/**
* Endpoint constructor.
* @param Client $client
*/
public function __construct(Client $client)
{
$this->setClient($client);
}
/**
* @param Client $client
* @return void
*/
public function setClient(Client $client)
{
$this->client = $client;
}
/**
* @return Client
*/
public function getClient()
{
return $this->client;
}
/**
* @return CacheInterface
*/
public function getCache()
{
return $this->getClient()->getCache();
}
/**
* @return string
*/
public function getPath()
{
$parentClass = \get_called_class();
return $parentClass::ENDPOINT;
}
/**
* Used to run endpoint onto given Client
*/
abstract public function handle();
/**
* @param array $body
* @param bool $ignoreCache
* @param bool $asArray
* @return array|ResponseInterface
* @throws ApiError
*/
protected function request(array $body = [], $asArray = true)
{
$parentClass = \get_called_class();
$response = $this->getClient()->makeRequest($parentClass::METHOD, $parentClass::ENDPOINT, $body, $asArray);
return $response;
}
}

View File

@@ -0,0 +1,61 @@
<?php
namespace Weglot\Client\Endpoint;
use Weglot\Client\Api\LanguageCollection;
use Weglot\Client\Factory\Languages as LanguagesFactory;
use Languages\Languages;
/**
* Class Languages
* @package Weglot\Client\Endpoint
*/
class LanguagesList extends Endpoint
{
const METHOD = 'GET';
const ENDPOINT = '/languages';
public function getLanguages(){
$data = Languages::$defaultLanguages;
return $data;
}
/**
* @return LanguageCollection
*/
public function handle()
{
$languageCollection = new LanguageCollection();
$data = Languages::$defaultLanguages;
$data = array_map(function($data) {
$external_code = $data['code'];
if($external_code == 'tw') {
$external_code = 'zh-tw';
}
if($external_code == 'br') {
$external_code = 'pt-br';
}
if($external_code == 'sa') {
$external_code = 'sr-lt';
}
return array(
'internal_code' => $data['code'],
'english' => $data['english'],
'local' => $data['local'],
'rtl' => $data['rtl'],
'external_code' => $external_code
);
}, $data);
foreach ($data as $language) {
if($language['internal_code'] != 'fc'){
$factory = new LanguagesFactory($language);
$languageCollection->addOne($factory->handle());
}
}
return $languageCollection;
}
}

View File

@@ -0,0 +1,29 @@
<?php
namespace Weglot\Client\Endpoint;
use Weglot\Client\Api\Exception\ApiError;
/**
* Class Status
* @package Weglot\Client\Endpoint
*/
class Status extends Endpoint
{
const METHOD = 'GET';
const ENDPOINT = '/status';
/**
* @return bool
* @throws ApiError
*/
public function handle()
{
list($rawBody, $httpStatusCode, $httpHeader) = $this->request([], false);
if ($httpStatusCode === 200) {
return true;
}
return false;
}
}

Some files were not shown because too many files have changed in this diff Show More