diff --git a/.gitignore b/.gitignore index 66be2e1..0823947 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,4 @@ bower_components/ config/config.yml docs/ clover.xml +i18n/*/LC_MESSAGES/*.mo diff --git a/Gruntfile.js b/Gruntfile.js index 8f75c48..aa1a811 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -90,6 +90,22 @@ module.exports = function (grunt) { package: { src: 'package.json' } + }, + potomo: { + dist: { + options: { + poDel: false + }, + files: { + 'i18n/fr_FR/LC_MESSAGES/Alltube.mo': 'i18n/fr_FR/LC_MESSAGES/Alltube.po', + 'i18n/zh_CN/LC_MESSAGES/Alltube.mo': 'i18n/zh_CN/LC_MESSAGES/Alltube.po' + } + } + }, + csslint: { + css: { + src: 'css/*' + } } } ); @@ -105,9 +121,11 @@ module.exports = function (grunt) { grunt.loadNpmTasks('grunt-phpdocumentor'); grunt.loadNpmTasks('grunt-jsonlint'); grunt.loadNpmTasks('grunt-fixpack'); + grunt.loadNpmTasks('grunt-potomo'); + grunt.loadNpmTasks('grunt-contrib-csslint'); - grunt.registerTask('default', ['uglify', 'cssmin']); - grunt.registerTask('lint', ['jslint', 'fixpack', 'jsonlint', 'phpcs']); + grunt.registerTask('default', ['uglify', 'cssmin', 'potomo']); + grunt.registerTask('lint', ['jslint', 'csslint', 'fixpack', 'jsonlint', 'phpcs']); grunt.registerTask('test', ['phpunit']); grunt.registerTask('doc', ['phpdocumentor']); grunt.registerTask('release', ['default', 'githash', 'compress']); diff --git a/classes/Config.php b/classes/Config.php index 306c28e..6226f26 100644 --- a/classes/Config.php +++ b/classes/Config.php @@ -38,7 +38,7 @@ class Config * * @var array */ - public $params = ['--no-warnings', '--ignore-errors', '--flat-playlist']; + public $params = ['--no-warnings', '--ignore-errors', '--flat-playlist', '--restrict-filenames']; /** * Enable audio conversion. diff --git a/classes/Locale.php b/classes/Locale.php new file mode 100644 index 0000000..cf6f602 --- /dev/null +++ b/classes/Locale.php @@ -0,0 +1,95 @@ +language = $parse[1]['language']; + $this->region = $parse[1]['region']; + } + + /** + * Convert the locale to a string. + * + * @return string ISO 15897 code + */ + public function __toString() + { + return $this->getIso15897(); + } + + /** + * Get the full name of the locale. + * + * @return string + */ + public function getFullName() + { + return \Locale::getDisplayName($this->getIso15897(), $this->getIso15897()); + } + + /** + * Get the ISO 15897 code. + * + * @return string + */ + public function getIso15897() + { + return $this->language.'_'.$this->region; + } + + /** + * Get the BCP 47 code. + * + * @return string + */ + public function getBcp47() + { + return $this->language.'-'.$this->region; + } + + /** + * Get the ISO 3166 code. + * + * @return string + */ + public function getIso3166() + { + return strtolower($this->region); + } + + public function getCountry() + { + return country($this->getIso3166()); + } +} diff --git a/classes/LocaleManager.php b/classes/LocaleManager.php new file mode 100644 index 0000000..d822588 --- /dev/null +++ b/classes/LocaleManager.php @@ -0,0 +1,87 @@ +newInstance($cookies); + $this->sessionSegment = $session->getSegment('Alltube\LocaleManager'); + $cookieLocale = $this->sessionSegment->get('locale'); + if (isset($cookieLocale)) { + $this->setLocale(new Locale($cookieLocale)); + } + } + + /** + * Get a list of supported locales. + * + * @return Locale[] + */ + public function getSupportedLocales() + { + $return = []; + foreach ($this->supportedLocales as $supportedLocale) { + $return[] = new Locale($supportedLocale); + } + + return $return; + } + + /** + * Get the current locale. + * + * @return Locale + */ + public function getLocale() + { + return $this->curLocale; + } + + /** + * Set the current locale. + * + * @param Locale $locale Locale + */ + public function setLocale(Locale $locale) + { + putenv('LANG='.$locale); + setlocale(LC_ALL, [$locale, $locale.'.utf8']); + $this->curLocale = $locale; + $this->sessionSegment->set('locale', $locale); + } +} diff --git a/classes/LocaleMiddleware.php b/classes/LocaleMiddleware.php new file mode 100644 index 0000000..51dfe6e --- /dev/null +++ b/classes/LocaleMiddleware.php @@ -0,0 +1,80 @@ +localeManager = $container->get('locale'); + } + + /** + * Test if a locale can be used for the current user. + * + * @param array $proposedLocale Locale array created by AcceptLanguage::parse() + * + * @return string Locale name if chosen, nothing otherwise + */ + public function testLocale(array $proposedLocale) + { + foreach ($this->localeManager->getSupportedLocales() as $locale) { + $parsedLocale = AcceptLanguage::parse($locale); + if (isset($proposedLocale['language']) + && $parsedLocale[1]['language'] == $proposedLocale['language'] + && $parsedLocale[1]['region'] == $proposedLocale['region'] + ) { + return new Locale($proposedLocale['language'].'_'.$proposedLocale['region']); + } + } + } + + /** + * Main middleware function. + * + * @param Request $request PSR request + * @param Response $response PSR response + * @param callable $next Next middleware + * + * @return Response + */ + public function __invoke(Request $request, Response $response, callable $next) + { + $headers = $request->getHeader('Accept-Language'); + $curLocale = $this->localeManager->getLocale(); + if (!isset($curLocale)) { + if (isset($headers[0])) { + $this->localeManager->setLocale( + AcceptLanguage::detect([$this, 'testLocale'], new Locale('en_US'), $headers[0]) + ); + } else { + $this->localeManager->setLocale(new Locale('en_US')); + } + } + + return $next($request, $response); + } +} diff --git a/composer.json b/composer.json index 14ab4cf..310215c 100644 --- a/composer.json +++ b/composer.json @@ -13,7 +13,10 @@ "ptachoire/process-builder-chain": "~1.2.0", "guzzlehttp/guzzle": "~6.2.0", "aura/session": "~2.1.0", - "barracudanetworks/archivestream-php": "~1.0.5" + "barracudanetworks/archivestream-php": "~1.0.5", + "smarty-gettext/smarty-gettext": "~1.5.1", + "zonuexe/http-accept-language": "~0.4.1", + "rinvex/country": "~2.0.0" }, "require-dev": { "symfony/var-dumper": "~3.2.0", diff --git a/composer.lock b/composer.lock index f3b33db..c5368cc 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "content-hash": "73d6ed72dae93290d21ac47042e14886", + "content-hash": "22e16312bcf339c90850660d9e5923e7", "packages": [ { "name": "aura/session", @@ -591,6 +591,80 @@ "description": "Add ability to chain symfony processes", "time": "2016-04-10T08:33:20+00:00" }, + { + "name": "rinvex/country", + "version": "v2.0.0", + "source": { + "type": "git", + "url": "https://github.com/rinvex/country.git", + "reference": "9405da035644bc76671bfba0c282fef8fd3408e1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/rinvex/country/zipball/9405da035644bc76671bfba0c282fef8fd3408e1", + "reference": "9405da035644bc76671bfba0c282fef8fd3408e1", + "shasum": "" + }, + "require": { + "php": ">=5.5.9" + }, + "require-dev": { + "phpunit/phpunit": "^5.2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "files": [ + "src/helpers.php" + ], + "psr-4": { + "Rinvex\\Country\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Rinvex LLC", + "email": "help@rinvex.com", + "homepage": "https://rinvex.com" + }, + { + "name": "Abdelrahman Omran", + "email": "me@omranic.com", + "homepage": "https://omranic.com", + "role": "Project Lead" + }, + { + "name": "The Generous Laravel Community", + "homepage": "https://github.com/rinvex/country/contributors" + } + ], + "description": "Rinvex Country is a simple and lightweight package for retrieving country details with flexibility. A whole bunch of data including name, demonym, capital, iso codes, dialling codes, geo data, currencies, flags, emoji, and other attributes for all 250 countries worldwide at your fingertips.", + "homepage": "https://rinvex.com", + "keywords": [ + "Flexible", + "Simple", + "countries", + "country", + "currencies", + "demonym", + "dialling", + "emoji", + "flags", + "geographic", + "languages", + "rinvex", + "svg" + ], + "time": "2016-11-27T05:53:11+00:00" + }, { "name": "slim/slim", "version": "3.8.1", @@ -662,6 +736,60 @@ ], "time": "2017-03-19T17:55:20+00:00" }, + { + "name": "smarty-gettext/smarty-gettext", + "version": "1.5.1", + "source": { + "type": "git", + "url": "https://github.com/smarty-gettext/smarty-gettext.git", + "reference": "00fe2fcbc41e24e0245cd9d73f96bc7b0337972d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/smarty-gettext/smarty-gettext/zipball/00fe2fcbc41e24e0245cd9d73f96bc7b0337972d", + "reference": "00fe2fcbc41e24e0245cd9d73f96bc7b0337972d", + "shasum": "" + }, + "require": { + "ext-gettext": "*", + "ext-pcre": "*", + "php": "~5.3|~7.0" + }, + "require-dev": { + "azatoth/php-pgettext": "~1.0", + "smarty/smarty": "3.1.*" + }, + "suggest": { + "azatoth/php-pgettext": "Support msgctxt for {t} via context parameter" + }, + "bin": [ + "tsmarty2c.php" + ], + "type": "library", + "autoload": { + "files": [ + "block.t.php", + "function.locale.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-2.1+" + ], + "authors": [ + { + "name": "Sagi Bashari", + "email": "sagi@boom.org.il" + }, + { + "name": "Elan Ruusamäe", + "email": "glen@delfi.ee" + } + ], + "description": "Gettext plugin enabling internationalization in Smarty Package files", + "homepage": "https://github.com/smarty-gettext/smarty-gettext", + "time": "2017-05-12T12:14:46+00:00" + }, { "name": "smarty/smarty", "version": "v3.1.31", @@ -717,16 +845,16 @@ }, { "name": "symfony/process", - "version": "v3.2.8", + "version": "v3.2.9", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "999c2cf5061e627e6cd551dc9ebf90dd1d11d9f0" + "reference": "36774717bbd1631be2d0a45acf48aecd5836c867" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/999c2cf5061e627e6cd551dc9ebf90dd1d11d9f0", - "reference": "999c2cf5061e627e6cd551dc9ebf90dd1d11d9f0", + "url": "https://api.github.com/repos/symfony/process/zipball/36774717bbd1631be2d0a45acf48aecd5836c867", + "reference": "36774717bbd1631be2d0a45acf48aecd5836c867", "shasum": "" }, "require": { @@ -762,20 +890,20 @@ ], "description": "Symfony Process Component", "homepage": "https://symfony.com", - "time": "2017-04-12T14:13:17+00:00" + "time": "2017-05-08T01:51:21+00:00" }, { "name": "symfony/yaml", - "version": "v3.2.8", + "version": "v3.2.9", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "acec26fcf7f3031e094e910b94b002fa53d4e4d6" + "reference": "4cdb9fec28fba88203a71f6d095018867f7a2065" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/acec26fcf7f3031e094e910b94b002fa53d4e4d6", - "reference": "acec26fcf7f3031e094e910b94b002fa53d4e4d6", + "url": "https://api.github.com/repos/symfony/yaml/zipball/4cdb9fec28fba88203a71f6d095018867f7a2065", + "reference": "4cdb9fec28fba88203a71f6d095018867f7a2065", "shasum": "" }, "require": { @@ -817,7 +945,48 @@ ], "description": "Symfony Yaml Component", "homepage": "https://symfony.com", - "time": "2017-05-01T14:55:58+00:00" + "time": "2017-05-25T23:42:36+00:00" + }, + { + "name": "zonuexe/http-accept-language", + "version": "0.4.1", + "source": { + "type": "git", + "url": "https://github.com/BaguettePHP/http-accept-language.git", + "reference": "f71422b1200737aa9d7c7fa83f07cbe4616198d5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/BaguettePHP/http-accept-language/zipball/f71422b1200737aa9d7c7fa83f07cbe4616198d5", + "reference": "f71422b1200737aa9d7c7fa83f07cbe4616198d5", + "shasum": "" + }, + "require": { + "ext-intl": "*" + }, + "require-dev": { + "phploc/phploc": "*", + "phpunit/phpunit": "4.1.*", + "theseer/phpdox": "0.6.*" + }, + "type": "library", + "autoload": { + "psr-4": { + "Teto\\HTTP\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "USAMI Kenta", + "email": "tadsan@zonu.me" + } + ], + "description": "HTTP Accept-Language Header parser", + "time": "2014-10-19T09:22:18+00:00" } ], "packages-dev": [ @@ -2238,16 +2407,16 @@ }, { "name": "symfony/var-dumper", - "version": "v3.2.8", + "version": "v3.2.9", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "fa47963ac7979ddbd42b2d646d1b056bddbf7bb8" + "reference": "eda0d0891a0b60a25015f7b85ea8040b51d72e1e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/fa47963ac7979ddbd42b2d646d1b056bddbf7bb8", - "reference": "fa47963ac7979ddbd42b2d646d1b056bddbf7bb8", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/eda0d0891a0b60a25015f7b85ea8040b51d72e1e", + "reference": "eda0d0891a0b60a25015f7b85ea8040b51d72e1e", "shasum": "" }, "require": { @@ -2302,7 +2471,7 @@ "debug", "dump" ], - "time": "2017-05-01T14:55:58+00:00" + "time": "2017-05-15T12:02:31+00:00" }, { "name": "webmozart/assert", diff --git a/controllers/FrontController.php b/controllers/FrontController.php index bbcc358..3318048 100644 --- a/controllers/FrontController.php +++ b/controllers/FrontController.php @@ -6,6 +6,7 @@ namespace Alltube\Controller; use Alltube\Config; +use Alltube\Locale; use Alltube\PasswordException; use Alltube\VideoDownload; use Psr\Container\ContainerInterface; @@ -61,6 +62,13 @@ class FrontController */ private $defaultFormat = 'best[protocol^=http]'; + /** + * LocaleManager instance. + * + * @var LocaleManager + */ + private $localeManager; + /** * FrontController constructor. * @@ -78,6 +86,7 @@ class FrontController $this->download = new VideoDownload(); $this->container = $container; $this->view = $this->container->get('view'); + $this->localeManager = $this->container->get('locale'); $session_factory = new \Aura\Session\SessionFactory(); $session = $session_factory->newInstance($cookies); $this->sessionSegment = $session->getSegment('Alltube\Controller\FrontController'); @@ -101,17 +110,35 @@ class FrontController $response, 'index.tpl', [ - 'config' => $this->config, - 'class' => 'index', - 'description' => 'Easily download videos from Youtube, Dailymotion, Vimeo and other websites.', - 'domain' => $uri->getScheme().'://'.$uri->getAuthority(), - 'canonical' => $this->getCanonicalUrl($request), + 'config' => $this->config, + 'class' => 'index', + 'description' => 'Easily download videos from Youtube, Dailymotion, Vimeo and other websites.', + 'domain' => $uri->getScheme().'://'.$uri->getAuthority(), + 'canonical' => $this->getCanonicalUrl($request), + 'supportedLocales' => $this->localeManager->getSupportedLocales(), + 'locale' => $this->localeManager->getLocale(), ] ); return $response; } + /** + * Switch locale. + * + * @param Request $request PSR-7 request + * @param Response $response PSR-7 response + * @param array $data Query parameters + * + * @return Response + */ + public function locale(Request $request, Response $response, array $data) + { + $this->localeManager->setLocale(new Locale($data['locale'])); + + return $response->withRedirect($this->container->get('router')->pathFor('index')); + } + /** * Display a list of extractors. * @@ -132,6 +159,7 @@ class FrontController 'description' => 'List of all supported websites from which Alltube Download '. 'can extract video or audio files', 'canonical' => $this->getCanonicalUrl($request), + 'locale' => $this->localeManager->getLocale(), ] ); @@ -156,6 +184,7 @@ class FrontController 'title' => 'Password prompt', 'description' => 'You need a password in order to download this video with Alltube Download', 'canonical' => $this->getCanonicalUrl($request), + 'locale' => $this->localeManager->getLocale(), ] ); @@ -246,6 +275,7 @@ class FrontController 'protocol' => $protocol, 'config' => $this->config, 'canonical' => $this->getCanonicalUrl($request), + 'locale' => $this->localeManager->getLocale(), ] ); @@ -297,6 +327,7 @@ class FrontController 'class' => 'video', 'title' => 'Error', 'canonical' => $this->getCanonicalUrl($request), + 'locale' => $this->localeManager->getLocale(), ] ); diff --git a/css/style.css b/css/style.css index a055a97..eefeedb 100644 --- a/css/style.css +++ b/css/style.css @@ -1,10 +1,10 @@ body { - text-align:center; background-color: #EBEBEB; background-image:url('../img/fond.jpg'); font-family: 'Open Sans', sans-serif; font-weight:400; + text-align:center; } @@ -12,90 +12,90 @@ body { /************************HEADER******************************/ header { - position:absolute; - top:0; - text-align:right; - width:100%; padding:0; - } + position:absolute; + text-align:right; + top:0; + width:100%; +} -.social -{padding-right:21px;} +.social { + padding-right:21px; +} -header a -{ -overflow:hidden; -height:38px; -width:38px; -position:relative; -float:right; -margin-top:13px; -margin-left:13px; -margin-right:0; -background-position:0 0; -background-repeat:no-repeat; - -webkit-transition: all 0.1s ease-in; - -moz-transition: all 0.1s ease-in; - -o-transition: all 0.1s ease-in; +header .social a { + background-position:0 0; + background-repeat:no-repeat; + float:right; + height:38px; + margin-left:13px; + margin-right:0; + margin-top:13px; + overflow:hidden; + position:relative; + -webkit-transition: all 0.1s ease-in; + -moz-transition: all 0.1s ease-in; + -o-transition: all 0.1s ease-in; + width:38px; } header a:focus, -header a:hover -{ - outline:none; +header a:hover { background-position:0 100%; - -webkit-transition: all 0.1s ease-in; - -moz-transition: all 0.1s ease-in; - -o-transition: all 0.1s ease-in; + outline:none; + -webkit-transition: all 0.1s ease-in; + -moz-transition: all 0.1s ease-in; + -o-transition: all 0.1s ease-in; } -.share -{background-image:url('../img/share.png');} - -.sharemask -{ -height:38px; -width:38px; -position:absolute; -top:0; -left:0; -z-index:10; -background-image:url('../img/sharemask.png'); -background-position:top left; -background-repeat:no-repeat; +.share { + background-image:url('../img/share.png'); } -.facebook -{background-image:url('../img/facebook.png');} +.sharemask { + background-image:url('../img/sharemask.png'); + background-position:top left; + background-repeat:no-repeat; + height:38px; + left:0; + position:absolute; + top:0; + width:38px; + z-index:10; -.facebookmask -{ -height:38px; -width:38px; -position:absolute; -top:0; -left:0; -z-index:10; -background-image:url('../img/facebookmask.png'); -background-position:top left; -background-repeat:no-repeat; } -.twitter -{background-image:url('../img/twitter.png');} +.facebook { + background-image:url('../img/facebook.png'); +} -.twittermask -{ -height:38px; -width:38px; -position:absolute; -top:0; -left:0; -z-index:10; -background-image:url('../img/twittermask.png'); -background-position:top left; -background-repeat:no-repeat; +.facebookmask { + background-image:url('../img/facebookmask.png'); + background-position:top left; + background-repeat:no-repeat; + height:38px; + left:0; + position:absolute; + top:0; + width:38px; + z-index:10; +} + +.twitter { + background-image:url('../img/twitter.png'); +} + +.twittermask { + background-image:url('../img/twittermask.png'); + background-position:top left; + background-repeat:no-repeat; + height:38px; + left:0; + position:absolute; + top:0; + width:38px; + z-index:10; } @@ -104,16 +104,16 @@ background-repeat:no-repeat; footer { - position:fixed; - bottom:0; - text-align:center; - width:100%; background-image:url('../img/fondfooter.png'); - background-repeat:repeat-x; background-position:top left; - padding-top:20px; + background-repeat:repeat-x; + bottom:0; color:#adadad; font-size:12px; + padding-top:20px; + position:fixed; + text-align:center; + width:100%; z-index:11; } @@ -123,20 +123,19 @@ footer { footer a{ color:#adadad; - -webkit-transition: all 0.1s ease-in; - -moz-transition: all 0.1s ease-in; - -o-transition: all 0.1s ease-in; - text-decoration:none; + text-decoration:none; + -webkit-transition: all 0.1s ease-in; + -moz-transition: all 0.1s ease-in; + -o-transition: all 0.1s ease-in; } footer a:focus, -footer a:hover -{ +footer a:hover { + color:#f2084a; outline:none; -color:#f2084a; - -webkit-transition: all 0.1s ease-in; - -moz-transition: all 0.1s ease-in; - -o-transition: all 0.1s ease-in; + -webkit-transition: all 0.1s ease-in; + -moz-transition: all 0.1s ease-in; + -o-transition: all 0.1s ease-in; } @@ -150,46 +149,42 @@ color:#f2084a; padding-bottom:55px; } -.labelurl -{ -position:relative; -color:#3f3f3f; -font-size:19px; - +.labelurl { + color:#3f3f3f; + font-size:19px; + position:relative; } -.champs -{ -position:relative; -margin-bottom:70px; -margin-top:8px; +.champs { + margin-bottom:70px; + margin-top:8px; + position:relative; } .downloadBtn { - position:relative; background-color:#3A3A3A; border: 3px solid #a5a5a5; - color:#dedede; border-radius:10px; - padding: 12px 14px; + color:#dedede; + cursor:pointer; + display:inline-block; font-size:24px; font-weight:800; - cursor:pointer; + padding: 12px 14px; + position:relative; + text-decoration:none; -webkit-transition: all 0.1s ease-in; -moz-transition: all 0.1s ease-in; -o-transition: all 0.1s ease-in; - text-decoration:none; - display:inline-block; } .downloadBtn:focus, -.downloadBtn:hover -{ - outline:none; +.downloadBtn:hover { background-color:#f2084a; - -webkit-transition: all 0.1s ease-in; - -moz-transition: all 0.1s ease-in; - -o-transition: all 0.1s ease-in; + outline:none; + -webkit-transition: all 0.1s ease-in; + -moz-transition: all 0.1s ease-in; + -o-transition: all 0.1s ease-in; } .downloadBtn::-moz-focus-inner { @@ -197,22 +192,22 @@ margin-top:8px; } .URLinput{ - position:relative; background-color:#fff; border: 3px solid #a5a5a5; - color:#3F3F3F; border-radius:10px; - padding: 12px 12px 12px 12px; - min-width:426px; + color:#3F3F3F; font-size:24px; font-weight:800; margin-right:8px; + min-width:426px; + padding: 12px 12px 12px 12px; + position:relative; } .URLinput:focus { - outline: none; border-color:#3A3A3A; + outline: none; } .URLinput:-webkit-input-placeholder{ @@ -223,176 +218,167 @@ margin-top:8px; } .combatiblelink { -position:relative; -color:#a5a5a5; -font-size:13px; -z-index:10; -text-decoration:none; -background-image:url('../img/compatiblerouage.png'); -background-position:0 100%; -background-repeat:no-repeat; -padding-left:41px; -padding-top:10px; -padding-bottom:10px; - -webkit-transition: all 0.1s ease-in; - -moz-transition: all 0.1s ease-in; - -o-transition: all 0.1s ease-in; + background-image:url('../img/compatiblerouage.png'); + background-position:0 100%; + background-repeat:no-repeat; + color:#a5a5a5; + font-size:13px; + padding-bottom:10px; + padding-left:41px; + padding-top:10px; + position:relative; + text-decoration:none; + -webkit-transition: all 0.1s ease-in; + -moz-transition: all 0.1s ease-in; + -o-transition: all 0.1s ease-in; + z-index:10; } .combatiblelink:focus, -.combatiblelink:hover -{ +.combatiblelink:hover { + background-position:0 0; + color:#f2084a; outline:none; -background-position:0 0; -color:#f2084a; - -webkit-transition: all 0.1s ease-in; - -moz-transition: all 0.1s ease-in; - -o-transition: all 0.1s ease-in; + -webkit-transition: all 0.1s ease-in; + -moz-transition: all 0.1s ease-in; + -o-transition: all 0.1s ease-in; } -#bookmarklet{ -padding:15px; -} - -.bookmarklet{ -position:relative; -font-size:13px; -color:gray; -z-index:10; -text-decoration:none; -padding-left:30px; -padding-right:30px; -padding-top:10px; -padding-bottom:10px; -border: 2px dotted; -} - -.mp3 -{ +.bookmarklet { + border: 2px dotted; + color:gray; + font-size:13px; + padding:10px 30px; position:relative; + text-decoration:none; + z-index:10; +} + +.mp3 { background-color:#cecece; - color:#696969; border-radius:6px; - width:622px; + color:#696969; font-size:14px; + font-weight:300; height:26px; margin-top:12px; + position:relative; text-align:left; - font-weight:300; + width:622px; } -.mp3 p -{ -padding:3px; +.mp3 p { + padding:3px; } - /* - Demo CSS code - */ +.audio:not(:checked), +.audio:checked { + left: -9999px; + position: absolute; +} +.audio:not(:checked) + label, +.audio:checked + label { + cursor: pointer; + line-height:22px; + padding-left: 82px; + position: relative; +} +.audio:not(:checked) + label:before, +.audio:checked + label:before, +.audio:not(:checked) + label:after, +.audio:checked + label:after { + content: ''; + position: absolute; +} +.audio:not(:checked) + label:before, +.audio:checked + label:before { + background: #ffffff; + border-radius: 6px; + height: 20px; + left:0; + top: -1px; + -webkit-transition: background-color .2s; + -moz-transition: background-color .2s; + -ms-transition: background-color .2s; + -o-transition: background-color .2s; + transition: background-color .2s; + width: 45px; +} +.audio:not(:checked) + label:after, +.audio:checked + label:after { + background: #3a3a3a; + border-radius: 6px; + height: 16px; + left: 2px; + top: 1px; + -webkit-transition: all .2s; + -moz-transition: all .2s; + -ms-transition: all .2s; + -o-transition: all .2s; + transition: all .2s; + width: 16px; +} - .audio:not(:checked), - .audio:checked { - position: absolute; - left: -9999px; - } - .audio:not(:checked) + label, - .audio:checked + label { - position: relative; - padding-left: 82px; - cursor: pointer; - line-height:22px; - } - .audio:not(:checked) + label:before, - .audio:checked + label:before, - .audio:not(:checked) + label:after, - .audio:checked + label:after { - content: ''; - position: absolute; - } - .audio:not(:checked) + label:before, - .audio:checked + label:before { - left:0; top: -1px; - width: 45px; height: 20px; - background: #ffffff; - border-radius: 6px; - -webkit-transition: background-color .2s; - -moz-transition: background-color .2s; - -ms-transition: background-color .2s; - -o-transition: background-color .2s; - transition: background-color .2s; - } - .audio:not(:checked) + label:after, - .audio:checked + label:after { - width: 16px; height: 16px; - -webkit-transition: all .2s; - -moz-transition: all .2s; - -ms-transition: all .2s; - -o-transition: all .2s; - transition: all .2s; - border-radius: 6px; - background: #3a3a3a; - top: 1px; left: 2px; - } +.audio:focus + label { + color:black; +} - .audio:focus + label { - color:black; - } +/* on checked */ +.audio:checked + label:before { + background:#f2084a; +} +.audio:checked + label:after { + background: #fff; + left: 27px; + top: 1px; +} - /* on checked */ - .audio:checked + label:before { - background:#f2084a; - } - .audio:checked + label:after { - background: #fff; - top: 1px; left: 27px; - } - - .audio:checked + label .ui, - .audio:not(:checked) + label .ui:before, - .audio:checked + label .ui:after { - position: absolute; - left: 3px; - width: 45px; - border-radius: 15px; - font-size: 11px; - font-weight: bold; - line-height: 17px; - height:20px; - -webkit-transition: all .2s; - -moz-transition: all .2s; - -ms-transition: all .2s; - -o-transition: all .2s; - transition: all .2s; - } - .audio:not(:checked) + label .ui:before { - content: "no"; - left: 0; - padding-left:23px; - padding-top:2px; - background-image:url('../img/mp3hover.png'); - background-repeat:no-repeat; - background-position:right top; - width:56px; - -webkit-transition: all .2s; - -moz-transition: all .2s; - -ms-transition: all .2s; - -o-transition: all .2s; - transition: all .2s; - } - .audio:checked + label .ui:after { - content: "yes"; - color: #fff; - background-image:url('../img/mp3.png'); - background-repeat:no-repeat; - background-position:right top; - width:73px; - -webkit-transition: all .2s; - -moz-transition: all .2s; - -ms-transition: all .2s; - -o-transition: all .2s; - transition: all .2s; - } +.audio:checked + label .ui, +.audio:not(:checked) + label .ui:before, +.audio:checked + label .ui:after { + border-radius: 15px; + font-size: 11px; + font-weight: bold; + height:20px; + left: 3px; + line-height: 17px; + position: absolute; + -webkit-transition: all .2s; + -moz-transition: all .2s; + -ms-transition: all .2s; + -o-transition: all .2s; + transition: all .2s; + width: 45px; +} +.audio:not(:checked) + label .ui:before { + background-image:url('../img/mp3hover.png'); + background-position:right top; + background-repeat:no-repeat; + content: "no"; + left: 0; + padding-left:23px; + padding-top:2px; + -webkit-transition: all .2s; + -moz-transition: all .2s; + -ms-transition: all .2s; + -o-transition: all .2s; + transition: all .2s; + width:56px; +} +.audio:checked + label .ui:after { + background-image:url('../img/mp3.png'); + background-position:right top; + background-repeat:no-repeat; + color: #fff; + content: "yes"; + -webkit-transition: all .2s; + -moz-transition: all .2s; + -ms-transition: all .2s; + -o-transition: all .2s; + transition: all .2s; + width:73px; +} @@ -423,8 +409,8 @@ padding:3px; } .playlist-entry .downloadBtn { - font-size: 16px; border-width: 2px; + font-size: 16px; } @@ -432,98 +418,93 @@ padding:3px; /*************************CONTENT COMPATIBLES****************************/ -.logobis -{ -width:447px; -height:107px; -position:relative; -margin:0 auto 10px auto; +.logobis { + height:107px; + margin:0 auto 10px auto; + position:relative; + width:447px; } -.logocompatible -{ -width:447px; -height:107px; -background-image:url('../img/logocompatible.png'); -background-repeat:repeat-y; -background-position:0 0; - -webkit-transition: all 0.1s ease-in; - -moz-transition: all 0.1s ease-in; - -o-transition: all 0.1s ease-in; -display:block; +.logocompatible { + background-image:url('../img/logocompatible.png'); + background-position:0 0; + background-repeat:repeat-y; + display:block; + height:107px; + -webkit-transition: all 0.1s ease-in; + -moz-transition: all 0.1s ease-in; + -o-transition: all 0.1s ease-in; + width:447px; } .logocompatible:focus, .logocompatible:hover { - outline:none; background-position:0 100%; - -webkit-transition: all 0.1s ease-in; - -moz-transition: all 0.1s ease-in; - -o-transition: all 0.1s ease-in;} - - -.logocompatiblemask -{ -z-index:10; -position:absolute; -top:0; -left:0; -width:447px; -height:107px; -background-image:url('../img/logocompatiblemask.png'); -background-position:0 100%; -background-repeat:no-repeat; -} - -.titre -{ -font-family: 'Open Sans', sans-serif; -font-weight:300; -color:#383838; -font-size:48px; -} - -.tripleliste -{ -margin-top:80px; -width:800px; -position:relative; -margin-left:auto; -margin-right:auto; + outline:none; + -webkit-transition: all 0.1s ease-in; + -moz-transition: all 0.1s ease-in; + -o-transition: all 0.1s ease-in; } -.tripleliste ul -{ -margin-bottom:1em; -width:600px; -margin-left:120px;} +.logocompatiblemask { + background-image:url('../img/logocompatiblemask.png'); + background-position:0 100%; + background-repeat:no-repeat; + height:107px; + left:0; + position:absolute; + top:0; + width:447px; + z-index:10; +} -.tripleliste ul li -{text-align:left; -List-Style-Type:none; -color:#383838; -font-size:16px; +.titre { + color:#383838; + font-family: 'Open Sans', sans-serif; + font-size:48px; + font-weight:300; +} -width:200px; -float:left; -position:relative; +.tripleliste { + margin-left:auto; + margin-right:auto; + margin-top:80px; + position:relative; + width:800px; +} + + +.tripleliste ul { + margin-bottom:1em; + margin-left:120px; + width:600px; +} + +.tripleliste ul li { + color:#383838; + float:left; + font-size:16px; + list-style-type:none; + position:relative; + text-align:left; + width:200px; } html, body { - margin:0; height:100%; + margin:0; } .wrapper { - height:100%; - display:table; - margin:auto; - padding-bottom:110px; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; + display:table; + height:100%; + margin:auto; + padding-bottom:110px; } .main { display:table-cell; @@ -595,6 +576,66 @@ h1 { font-family:monospace; } +.locales { + float: left; + font-size: 12px; + padding-left: 1em; + padding-top: 1em; + text-align: left; +} + +.locales a, +.locales a:visited { + color: #696969; + text-decoration: none; +} + +.supportedLocales { + background-color: #fff; + list-style-type: none; + margin: 0; + opacity: 0; + padding-left: 0; + transition: visibility 0.5s; + visibility: hidden; +} + +.supportedLocales li { + border-bottom: thin solid #E1E1E1; +} + +.supportedLocales li:last-child { + border-bottom: none; +} + +.supportedLocales li a { + display: block; + padding: 1em; + padding-right: 2em; +} + +.supportedLocales li:hover { + background-color: #cecece; +} + +.localesBtn { + border: none; + cursor: pointer; + display: inline-block; + font-size: 12px; + padding: 1em; +} + +.localesBtn:focus { + background-color: #fff; + pointer-events: none; +} + +.localesBtn:focus + .supportedLocales { + opacity: 1; + visibility: visible; +} + @media (max-width: 640px) { .formats, .thumb { @@ -619,9 +660,9 @@ h1 { .champs, .URLinput, .mp3 { - width:90%; - margin:auto; height:auto; + margin:auto; + width:90%; } .logo { @@ -629,8 +670,8 @@ h1 { } .logocompatible img { - width:100%; height: auto; + width:100%; } .downloadBtn { @@ -646,9 +687,9 @@ h1 { .tripleliste ul, .tripleliste { - width:auto; margin-left:auto; margin-top:auto; + width:auto; } .logocompatiblemask { @@ -656,9 +697,9 @@ h1 { } .logocompatible { - height:auto; - background-image:none; background-color:#4F4F4F; + background-image:none; + height:auto; } .logocompatiblemask, diff --git a/i18n/fr_FR/LC_MESSAGES/Alltube.po b/i18n/fr_FR/LC_MESSAGES/Alltube.po new file mode 100644 index 0000000..8fcb988 --- /dev/null +++ b/i18n/fr_FR/LC_MESSAGES/Alltube.po @@ -0,0 +1,134 @@ +msgid "" +msgstr "" +"Project-Id-Version: \n" +"POT-Creation-Date: \n" +"PO-Revision-Date: \n" +"Last-Translator: Pierre Rudloff \n" +"Language-Team: \n" +"Language: fr_FR\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Poedit 1.6.10\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +#: templates/error.tpl:5 +msgid "An error occured" +msgstr "Une erreur est survenue" + +#: templates/error.tpl:6 +msgid "Please check the URL of your video." +msgstr "Veuillez vérifier l'URL de votre vidéo" + +#: templates/playlist.tpl:5 +msgid "Videos extracted from" +msgstr "Vidéos extraites depuis" + +#: templates/playlist.tpl:7 +msgid ":" +msgstr " :" + +#: templates/playlist.tpl:26 templates/password.tpl:10 templates/video.tpl:85 +#: templates/video.tpl:88 templates/index.tpl:18 +msgid "Download" +msgstr "Télécharger" + +#: templates/playlist.tpl:27 +msgid "More options" +msgstr "Plus d'options" + +#: templates/password.tpl:5 +msgid "This video is protected" +msgstr "Cette vidéo est protégée" + +#: templates/password.tpl:6 +msgid "You need a password in order to download this video." +msgstr "L'accès à cette vidéo nécessite un mot de passe." + +#: templates/password.tpl:8 +msgid "Video password" +msgstr "Mot de passe de la vidéo" + +#: templates/extractors.tpl:4 +msgid "Supported websites" +msgstr "Sites web supportés" + +#: templates/video.tpl:6 +msgid "You are going to download" +msgstr "Vous allez télécharger" + +#: templates/video.tpl:26 +msgid "Available formats:" +msgstr "Formats disponibles :" + +#: templates/video.tpl:31 +msgid "Generic formats" +msgstr "Formats génériques" + +#: templates/video.tpl:34 +msgid "Best" +msgstr "Meilleure qualité" + +#: templates/video.tpl:39 +msgid "Remux best video with best audio" +msgstr "Combiner la meilleure vidéo avec le meilleur audio" + +#: templates/video.tpl:43 +msgid "Worst" +msgstr "Pire qualité" + +#: templates/video.tpl:46 +msgid "Detailed formats" +msgstr "Formats détaillés" + +#: templates/inc/footer.tpl:4 +msgid "Code by" +msgstr "Développé par" + +#: templates/inc/footer.tpl:6 +msgid "Design by" +msgstr "Designé par" + +#: templates/inc/footer.tpl:12 +msgid "AllTube Download on Facebook" +msgstr "AllTube Download sur Facebook" + +#: templates/inc/footer.tpl:12 +msgid "Like us on Facebook" +msgstr "Suivez-nous sur Facebook" + +#: templates/inc/footer.tpl:14 +msgid "Get the code" +msgstr "Obtenir le code" + +#: templates/inc/footer.tpl:16 +msgid "Based on" +msgstr "Basé sur" + +#: templates/inc/header.tpl:4 +msgid "Share on Twitter" +msgstr "Partager sur Twitter" + +#: templates/inc/header.tpl:5 +msgid "Share on Facebook" +msgstr "Partager sur Facebook" + +#: templates/index.tpl:8 +msgid "Copy here the URL of your video (Youtube, Dailymotion, etc.)" +msgstr "Copiez ici l'URL de votre vidéo (Youtube, Dailymotion, etc.)" + +#: templates/index.tpl:23 +msgid "Audio only (MP3)" +msgstr "Audio uniquement (MP3)" + +#: templates/index.tpl:28 +msgid "See all supported websites" +msgstr "Voir tous les sites supportés" + +#: templates/index.tpl:30 +msgid "Drag this to your bookmarks bar:" +msgstr "Glissez ce lien dans votre barre de favoris :" + +#: templates/index.tpl:31 +msgid "Bookmarklet" +msgstr "Bookmarklet" diff --git a/i18n/template.pot b/i18n/template.pot new file mode 100644 index 0000000..7db980d --- /dev/null +++ b/i18n/template.pot @@ -0,0 +1,123 @@ +msgid "" +msgstr "Content-Type: text/plain; charset=UTF-8\n" + +#: templates/error.tpl:5 +msgid "An error occured" +msgstr "" + +#: templates/error.tpl:6 +msgid "Please check the URL of your video." +msgstr "" + +#: templates/playlist.tpl:5 +msgid "Videos extracted from" +msgstr "" + +#: templates/playlist.tpl:7 +msgid ":" +msgstr "" + +#: templates/playlist.tpl:26 templates/password.tpl:10 templates/video.tpl:85 +#: templates/video.tpl:88 templates/index.tpl:18 +msgid "Download" +msgstr "" + +#: templates/playlist.tpl:27 +msgid "More options" +msgstr "" + +#: templates/password.tpl:5 +msgid "This video is protected" +msgstr "" + +#: templates/password.tpl:6 +msgid "You need a password in order to download this video." +msgstr "" + +#: templates/password.tpl:8 +msgid "Video password" +msgstr "" + +#: templates/extractors.tpl:4 +msgid "Supported websites" +msgstr "" + +#: templates/video.tpl:6 +msgid "You are going to download" +msgstr "" + +#: templates/video.tpl:26 +msgid "Available formats:" +msgstr "" + +#: templates/video.tpl:31 +msgid "Generic formats" +msgstr "" + +#: templates/video.tpl:34 +msgid "Best" +msgstr "" + +#: templates/video.tpl:39 +msgid "Remux best video with best audio" +msgstr "" + +#: templates/video.tpl:43 +msgid "Worst" +msgstr "" + +#: templates/video.tpl:46 +msgid "Detailed formats" +msgstr "" + +#: templates/inc/footer.tpl:4 +msgid "Code by" +msgstr "" + +#: templates/inc/footer.tpl:6 +msgid "Design by" +msgstr "" + +#: templates/inc/footer.tpl:12 +msgid "AllTube Download on Facebook" +msgstr "" + +#: templates/inc/footer.tpl:12 +msgid "Like us on Facebook" +msgstr "" + +#: templates/inc/footer.tpl:14 +msgid "Get the code" +msgstr "" + +#: templates/inc/footer.tpl:16 +msgid "Based on" +msgstr "" + +#: templates/inc/header.tpl:4 +msgid "Share on Twitter" +msgstr "" + +#: templates/inc/header.tpl:5 +msgid "Share on Facebook" +msgstr "" + +#: templates/index.tpl:8 +msgid "Copy here the URL of your video (Youtube, Dailymotion, etc.)" +msgstr "" + +#: templates/index.tpl:23 +msgid "Audio only (MP3)" +msgstr "" + +#: templates/index.tpl:28 +msgid "See all supported websites" +msgstr "" + +#: templates/index.tpl:30 +msgid "Drag this to your bookmarks bar:" +msgstr "" + +#: templates/index.tpl:31 +msgid "Bookmarklet" +msgstr "" diff --git a/i18n/zh_CN/LC_MESSAGES/Alltube.po b/i18n/zh_CN/LC_MESSAGES/Alltube.po new file mode 100644 index 0000000..d0bc3e0 --- /dev/null +++ b/i18n/zh_CN/LC_MESSAGES/Alltube.po @@ -0,0 +1,135 @@ +msgid "" +msgstr "" +"Project-Id-Version: \n" +"POT-Creation-Date: \n" +"PO-Revision-Date: \n" +"Last-Translator: Shiqiang Yu \n" +"Language-Team: \n" +"Language: zh_CN\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Poedit 2.0.2\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +#: ..\..\..\templates/error.tpl:5 +msgid "An error occured" +msgstr "出错了" + +#: ..\..\..\templates/error.tpl:6 +msgid "Please check the URL of your video." +msgstr "请检查您的视频的 URL。" + +#: ..\..\..\templates/extractors.tpl:4 +msgid "Supported websites" +msgstr "支持的网站" + +#: ..\..\..\templates/inc/footer.tpl:4 +msgid "Code by" +msgstr "代码来自" + +#: ..\..\..\templates/inc/footer.tpl:6 +msgid "Design by" +msgstr "设计来自" + +#: ..\..\..\templates/inc/footer.tpl:12 +msgid "AllTube Download on Facebook" +msgstr "去Alltube Download的Facebook页面" + +#: ..\..\..\templates/inc/footer.tpl:12 +msgid "Like us on Facebook" +msgstr "在Facebook关注我们" + +#: ..\..\..\templates/inc/footer.tpl:14 +msgid "Get the code" +msgstr "获取代码" + +#: ..\..\..\templates/inc/footer.tpl:16 +msgid "Based on" +msgstr "基于" + +#: ..\..\..\templates/inc/header.tpl:4 +msgid "Share on Twitter" +msgstr "分享到 Twitter" + +#: ..\..\..\templates/inc/header.tpl:5 +msgid "Share on Facebook" +msgstr "分享到 Facebook" + +#: ..\..\..\templates/index.tpl:9 +msgid "Copy here the URL of your video (Youtube, Dailymotion, etc.)" +msgstr "在这里复制您的视频 (Youtube、 Dailymotion 等) 的 URL" + +#: ..\..\..\templates/index.tpl:19 ..\..\..\templates/password.tpl:10 +#: ..\..\..\templates/playlist.tpl:23 ..\..\..\templates/video.tpl:85 +#: ..\..\..\templates/video.tpl:90 +msgid "Download" +msgstr "下载" + +#: ..\..\..\templates/index.tpl:24 +msgid "Audio only (MP3)" +msgstr "仅限音频(mp3)" + +#: ..\..\..\templates/index.tpl:29 +msgid "See all supported websites" +msgstr "请参阅支持的所有网站" + +#: ..\..\..\templates/index.tpl:31 +msgid "Drag this to your bookmarks bar:" +msgstr "把这个拖到你的书签:" + +#: ..\..\..\templates/index.tpl:32 +msgid "Bookmarklet" +msgstr "书签工具" + +#: ..\..\..\templates/password.tpl:5 +msgid "This video is protected" +msgstr "这个视频受保护" + +#: ..\..\..\templates/password.tpl:6 +msgid "You need a password in order to download this video." +msgstr "你需要密码才能下载这个视频。" + +#: ..\..\..\templates/password.tpl:8 +msgid "Video password" +msgstr "视频密码" + +#: ..\..\..\templates/playlist.tpl:5 +msgid "Videos extracted from the" +msgstr "视频从" + +#: ..\..\..\templates/playlist.tpl:7 +msgid "playlist:" +msgstr "播放列表提取:" + +#: ..\..\..\templates/playlist.tpl:24 +msgid "More options" +msgstr "更多选项" + +#: ..\..\..\templates/video.tpl:6 +msgid "You are going to download" +msgstr "你即将下载" + +#: ..\..\..\templates/video.tpl:24 +msgid "Available formats:" +msgstr "可用的格式︰" + +#: ..\..\..\templates/video.tpl:31 +msgid "Generic formats" +msgstr "通用格式" + +#: ..\..\..\templates/video.tpl:34 +msgid "Best" +msgstr "最佳" + +#: ..\..\..\templates/video.tpl:39 +msgid "Remux best video with best audio" +msgstr "重新封装最佳视频与最佳音频" + +#: ..\..\..\templates/video.tpl:43 +msgid "Worst" +msgstr "最差" + +#: ..\..\..\templates/video.tpl:46 +msgid "Detailed formats" +msgstr "详细格式" diff --git a/index.php b/index.php index 3b55687..89d76e9 100644 --- a/index.php +++ b/index.php @@ -3,6 +3,8 @@ require_once __DIR__.'/vendor/autoload.php'; use Alltube\Config; use Alltube\Controller\FrontController; +use Alltube\LocaleManager; +use Alltube\LocaleMiddleware; use Alltube\PlaylistArchiveStream; use Alltube\UglyRouter; use Alltube\ViewFactory; @@ -22,6 +24,8 @@ if ($config->uglyUrls) { $container['router'] = new UglyRouter(); } $container['view'] = ViewFactory::create($container); +$container['locale'] = new LocaleManager($_COOKIE); +$app->add(new LocaleMiddleware($container)); $controller = new FrontController($container, null, $_COOKIE); @@ -43,4 +47,8 @@ $app->get( '/redirect', [$controller, 'redirect'] )->setName('redirect'); +$app->get( + '/locale/{locale}', + [$controller, 'locale'] +)->setName('locale'); $app->run(); diff --git a/package-lock.json b/package-lock.json index b3526d0..71c775c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -227,6 +227,11 @@ "version": "https://registry.npmjs.org/clean-css/-/clean-css-4.1.3.tgz", "integrity": "sha1-B8/omA7bINRV3cI6rc8eBMblCc4=" }, + "clone": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.1.tgz", + "integrity": "sha1-0hfR6WERjjrJpLi7oyhVU79kfNs=" + }, "co": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", @@ -303,6 +308,11 @@ "dev": true, "optional": true }, + "csslint": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/csslint/-/csslint-1.0.5.tgz", + "integrity": "sha1-Gcw+2jIhYP0/cjKvHLKjYOiYouk=" + }, "currently-unhandled": { "version": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=" @@ -579,6 +589,23 @@ } } }, + "grunt-contrib-csslint": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/grunt-contrib-csslint/-/grunt-contrib-csslint-2.0.0.tgz", + "integrity": "sha1-MSnZTf5Qc1fyMzfSSunpqkudV98=", + "dependencies": { + "lodash": { + "version": "4.17.4", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", + "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=" + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" + } + } + }, "grunt-contrib-cssmin": { "version": "https://registry.npmjs.org/grunt-contrib-cssmin/-/grunt-contrib-cssmin-2.2.0.tgz", "integrity": "sha1-ct70BijujiE62adoBNEx22ZgSkE=" @@ -676,6 +703,11 @@ "integrity": "sha1-DnW+5rXC5l/aRQdWcqBs6yzs2Gk=", "dev": true }, + "grunt-potomo": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/grunt-potomo/-/grunt-potomo-3.5.0.tgz", + "integrity": "sha1-WtjG9+djrVtRg55cbTI1gGLHN5U=" + }, "gzip-size": { "version": "https://registry.npmjs.org/gzip-size/-/gzip-size-3.0.0.tgz", "integrity": "sha1-VGGI6b3DN/Zzdy+BZgRks4nc5SA=" @@ -770,6 +802,11 @@ "integrity": "sha1-BTfLedr1m1mhpRff9wbIbsA5Fi4=", "dev": true }, + "interpret": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.0.3.tgz", + "integrity": "sha1-y8NcYu7uc/Gat7EKgBURQBr8D5A=" + }, "is-arrayish": { "version": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=" @@ -1139,6 +1176,11 @@ "version": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=" }, + "parserlib": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/parserlib/-/parserlib-1.1.1.tgz", + "integrity": "sha1-pkz6ckBiQ0/fw1HJpOwtkrlMBvQ=" + }, "parseurl": { "version": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.1.tgz", "integrity": "sha1-yKuMkiO6NIiKpkopeyiFO+wY2lY=", @@ -1236,6 +1278,11 @@ "version": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.2.9.tgz", "integrity": "sha1-z3jsb0ptHrQ9JkiMrJfwQudLf8g=" }, + "rechoir": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", + "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=" + }, "redent": { "version": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=" @@ -1288,6 +1335,11 @@ "dev": true, "optional": true }, + "shelljs": { + "version": "0.7.7", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.7.7.tgz", + "integrity": "sha1-svXHfvlxSPS09uImguELuoZnz/E=" + }, "signal-exit": { "version": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" diff --git a/package.json b/package.json index e62d84a..eb35557 100644 --- a/package.json +++ b/package.json @@ -7,8 +7,10 @@ "dependencies": { "bower": "~1.8.0", "grunt": "~1.0.1", + "grunt-contrib-csslint": "~2.0.0", "grunt-contrib-cssmin": "~2.2.0", - "grunt-contrib-uglify": "~3.0.0" + "grunt-contrib-uglify": "~3.0.0", + "grunt-potomo": "~3.5.0" }, "devDependencies": { "grunt-contrib-compress": "~1.4.1", diff --git a/templates/error.tpl b/templates/error.tpl index 67a0fae..ded9676 100644 --- a/templates/error.tpl +++ b/templates/error.tpl @@ -2,8 +2,8 @@
{include file="inc/logo.tpl"} -

An error occured

- Please check the URL of your video. +

{t}An error occured{/t}

+ {t}Please check the URL of your video.{/t}

{foreach $errors as $error} {$error|escape} diff --git a/templates/extractors.tpl b/templates/extractors.tpl index 4944193..fb85994 100644 --- a/templates/extractors.tpl +++ b/templates/extractors.tpl @@ -1,7 +1,7 @@ {include file='inc/head.tpl'} {include file='inc/header.tpl'} {include file='inc/logo.tpl'} -

Supported websites

+

{t}Supported websites{/t}

    {foreach $extractors as $extractor} diff --git a/templates/inc/footer.tpl b/templates/inc/footer.tpl index c5797fc..b9ff314 100644 --- a/templates/inc/footer.tpl +++ b/templates/inc/footer.tpl @@ -1,19 +1,19 @@
diff --git a/templates/inc/head.tpl b/templates/inc/head.tpl index 392c7c2..16e185f 100644 --- a/templates/inc/head.tpl +++ b/templates/inc/head.tpl @@ -1,5 +1,6 @@ +{locale path="../i18n" domain="Alltube"} - + diff --git a/templates/inc/header.tpl b/templates/inc/header.tpl index fc42083..4ae06cd 100644 --- a/templates/inc/header.tpl +++ b/templates/inc/header.tpl @@ -1,8 +1,26 @@
+ {if isset($supportedLocales)} +
+ + + {/if} +
diff --git a/templates/index.tpl b/templates/index.tpl index 41d6b3a..2f48a1f 100644 --- a/templates/index.tpl +++ b/templates/index.tpl @@ -5,7 +5,7 @@ alt="AllTube Download" width="328" height="284">
@@ -15,20 +15,20 @@ {if $config->uglyUrls} {/if} -
+
{if $config->convert}

+ {t}Audio only (MP3){/t}

{/if}
- See all supported websites + {t}See all supported websites{/t}
-

Drag this to your bookmarks bar:

- Bookmarklet +

{t}Drag this to your bookmarks bar:{/t}

+ {t}Bookmarklet{/t}
diff --git a/templates/password.tpl b/templates/password.tpl index ab8e302..a4c56f2 100644 --- a/templates/password.tpl +++ b/templates/password.tpl @@ -2,12 +2,12 @@
{include file="inc/logo.tpl"} -

This video is protected

-

You need a password in order to download this video.

+

{t}This video is protected{/t}

+

{t}You need a password in order to download this video.{/t}

- +

- +
{include file='inc/footer.tpl'} diff --git a/templates/playlist.tpl b/templates/playlist.tpl index 40f3669..742c31e 100644 --- a/templates/playlist.tpl +++ b/templates/playlist.tpl @@ -2,9 +2,9 @@
{include file="inc/logo.tpl"} -

Videos extracted from the {if isset($video->title)} +

{t}Videos extracted from{/t} {if isset($video->title)} -{$video->title}{/if} playlist: +{$video->title}{/if}{t}:{/t}

{if $config->stream} webpage_url}" class="downloadBtn">Download everything @@ -23,8 +23,8 @@ {$video->title} {/if} - url}">Download - url}">More options + url}">{t}Download{/t} + url}">{t}More options{/t}
{/foreach} diff --git a/templates/video.tpl b/templates/video.tpl index 0229f21..6abf0ba 100644 --- a/templates/video.tpl +++ b/templates/video.tpl @@ -3,7 +3,7 @@