mirror of
https://github.com/DirectoryLister/DirectoryLister.git
synced 2025-08-26 07:15:30 +02:00
Added translations
This commit is contained in:
@@ -14,6 +14,15 @@ return [
|
||||
*/
|
||||
'debug' => Helpers::env('DEBUG'),
|
||||
|
||||
/**
|
||||
* The application interface language.
|
||||
*
|
||||
* Possible values: See 'app/languages' folder for available translations.
|
||||
*
|
||||
* Defualt value: en
|
||||
*/
|
||||
'language' => Helpers::env('LANGUAGE'),
|
||||
|
||||
/**
|
||||
* Enable dark mode?
|
||||
*
|
||||
|
@@ -18,6 +18,7 @@ class AppManager
|
||||
protected const PROVIDERS = [
|
||||
Providers\ConfigProvider::class,
|
||||
Providers\FinderProvider::class,
|
||||
Providers\TranslationProvider::class,
|
||||
Providers\TwigProvider::class,
|
||||
Providers\WhoopsProvider::class,
|
||||
];
|
||||
|
@@ -7,24 +7,27 @@ use Psr\Http\Message\ServerRequestInterface;
|
||||
use Slim\Interfaces\ErrorHandlerInterface;
|
||||
use Slim\Psr7\Response;
|
||||
use Slim\Views\Twig;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
use Throwable;
|
||||
|
||||
class ErrorHandler implements ErrorHandlerInterface
|
||||
{
|
||||
/** @const The default error message string */
|
||||
protected const DEFAULT_ERROR_MESSAGE = 'An unexpected error occured';
|
||||
|
||||
/** @var Twig Twig templating component */
|
||||
protected $view;
|
||||
|
||||
/** @var TranslatorInterface Translation component */
|
||||
protected $translator;
|
||||
|
||||
/**
|
||||
* Create a new ErrorHandler object.
|
||||
*
|
||||
* @param \Slim\Views\Twig $view
|
||||
* @param \Slim\Views\Twig $view
|
||||
* @param \Symfony\Contracts\Translation\TranslatorInterface $translator
|
||||
*/
|
||||
public function __construct(Twig $view)
|
||||
public function __construct(Twig $view, TranslatorInterface $translator)
|
||||
{
|
||||
$this->view = $view;
|
||||
$this->translator = $translator;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -49,15 +52,15 @@ class ErrorHandler implements ErrorHandlerInterface
|
||||
|
||||
if (in_array('application/json', explode(',', $request->getHeaderLine('Accept')))) {
|
||||
$response->getBody()->write(json_encode([
|
||||
'error' => ['message' => self::DEFAULT_ERROR_MESSAGE]
|
||||
'error' => ['message' => $this->translator->trans('error.unexpected')]
|
||||
]));
|
||||
|
||||
return $response->withHeader('Content-Type', 'application/json');
|
||||
}
|
||||
|
||||
return $this->view->render($response, 'error.twig', [
|
||||
'message' => self::DEFAULT_ERROR_MESSAGE,
|
||||
'subtext' => 'Enable debugging for additional information',
|
||||
'message' => $this->translator->trans('error.unexpected'),
|
||||
'subtext' => $this->translator->trans('enable_debugging'),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
@@ -10,6 +10,7 @@ use Slim\Views\Twig;
|
||||
use Symfony\Component\Finder\Exception\DirectoryNotFoundException;
|
||||
use Symfony\Component\Finder\Finder;
|
||||
use Symfony\Component\Finder\SplFileInfo;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
|
||||
class DirectoryHandler
|
||||
{
|
||||
@@ -22,18 +23,27 @@ class DirectoryHandler
|
||||
/** @var Twig Twig templating component */
|
||||
protected $view;
|
||||
|
||||
/** @var TranslatorInterface Translator component */
|
||||
protected $translator;
|
||||
|
||||
/**
|
||||
* Create a new IndexController object.
|
||||
*
|
||||
* @param \PHLAK\Config\Config $config
|
||||
* @param \Symfony\Component\Finder\Finder $finder
|
||||
* @param \Slim\Views\Twig $view
|
||||
* @param \PHLAK\Config\Config $config
|
||||
* @param \Symfony\Component\Finder\Finder $finder
|
||||
* @param \Slim\Views\Twig $view
|
||||
* @param \Symfony\Contracts\Translation\TranslatorInterface $translator
|
||||
*/
|
||||
public function __construct(Config $config, Finder $finder, Twig $view)
|
||||
{
|
||||
public function __construct(
|
||||
Config $config,
|
||||
Finder $finder,
|
||||
Twig $view,
|
||||
TranslatorInterface $translator
|
||||
) {
|
||||
$this->config = $config;
|
||||
$this->finder = $finder;
|
||||
$this->view = $view;
|
||||
$this->translator = $translator;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -52,7 +62,7 @@ class DirectoryHandler
|
||||
$files = $this->finder->in($path)->depth(0);
|
||||
} catch (DirectoryNotFoundException $exception) {
|
||||
return $this->view->render($response->withStatus(404), 'error.twig', [
|
||||
'message' => 'Directory does not exist'
|
||||
'message' => $this->translator->trans('error.directory_not_found')
|
||||
]);
|
||||
}
|
||||
|
||||
|
@@ -8,6 +8,7 @@ use Psr\Http\Message\ResponseInterface;
|
||||
use Slim\Psr7\Request;
|
||||
use Slim\Psr7\Response;
|
||||
use SplFileInfo;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
|
||||
class FileInfoHandler
|
||||
{
|
||||
@@ -17,16 +18,24 @@ class FileInfoHandler
|
||||
/** @var Config App configuration component */
|
||||
protected $config;
|
||||
|
||||
/** @var TranslatorInterface Translator component */
|
||||
protected $translator;
|
||||
|
||||
/**
|
||||
* Create a new FileInfoHandler object.
|
||||
*
|
||||
* @param \DI\Container $container
|
||||
* @param \PHLAK\Config\Config $config
|
||||
* @param \DI\Container $container
|
||||
* @param \PHLAK\Config\Config $config
|
||||
* @param \Symfony\Contracts\Translation\TranslatorInterface $translator
|
||||
*/
|
||||
public function __construct(Container $container, Config $config)
|
||||
{
|
||||
public function __construct(
|
||||
Container $container,
|
||||
Config $config,
|
||||
TranslatorInterface $translator
|
||||
) {
|
||||
$this->container = $container;
|
||||
$this->config = $config;
|
||||
$this->translator = $translator;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -46,11 +55,11 @@ class FileInfoHandler
|
||||
);
|
||||
|
||||
if (! $file->isFile()) {
|
||||
return $response->withStatus(404, 'File not found');
|
||||
return $response->withStatus(404, $this->translator->trans('error.file_not_found'));
|
||||
}
|
||||
|
||||
if ($file->getSize() >= $this->config->get('app.max_hash_size', 1000000000)) {
|
||||
return $response->withStatus(500, 'File size too large');
|
||||
return $response->withStatus(500, $this->translator->trans('error.file_size_exceeded'));
|
||||
}
|
||||
|
||||
$response->getBody()->write(json_encode([
|
||||
|
@@ -7,6 +7,8 @@ use Slim\Psr7\Request;
|
||||
use Slim\Psr7\Response;
|
||||
use Slim\Views\Twig;
|
||||
use Symfony\Component\Finder\Finder;
|
||||
use Symfony\Component\Translation\Translator;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
|
||||
class SearchHandler
|
||||
{
|
||||
@@ -16,16 +18,21 @@ class SearchHandler
|
||||
/** @var Twig Twig templating component */
|
||||
protected $view;
|
||||
|
||||
/** @var TranslatorInterface Translator component */
|
||||
protected $translator;
|
||||
|
||||
/**
|
||||
* Create a new SearchHandler object.
|
||||
*
|
||||
* @param \Symfony\Component\Finder\Finder $finder
|
||||
* @param \Slim\Views\Twig $view
|
||||
* @param \Symfony\Component\Finder\Finder $finder
|
||||
* @param \Slim\Views\Twig $view
|
||||
* @param \Symfony\Contracts\Translation\TranslatorInterface $translator
|
||||
*/
|
||||
public function __construct(Finder $finder, Twig $view)
|
||||
public function __construct(Finder $finder, Twig $view, TranslatorInterface $translator)
|
||||
{
|
||||
$this->finder = $finder;
|
||||
$this->view = $view;
|
||||
$this->translator = $translator;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -42,7 +49,7 @@ class SearchHandler
|
||||
|
||||
if (empty($search)) {
|
||||
return $this->view->render($response, 'error.twig', [
|
||||
'message' => 'No results found'
|
||||
'message' => $this->translator->trans('error.no_results_found')
|
||||
]);
|
||||
}
|
||||
|
||||
|
@@ -10,6 +10,7 @@ use Slim\Psr7\Request;
|
||||
use Slim\Psr7\Response;
|
||||
use Symfony\Component\Finder\Finder;
|
||||
use Symfony\Component\Finder\SplFileInfo;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
use Tightenco\Collect\Support\Collection;
|
||||
use ZipArchive;
|
||||
|
||||
@@ -24,17 +25,25 @@ class ZipHandler
|
||||
/** @var Finder The Finder Component */
|
||||
protected $finder;
|
||||
|
||||
/** @var TranslatorInterface Translator component */
|
||||
protected $translator;
|
||||
|
||||
/**
|
||||
* Create a new ZipHandler object.
|
||||
*
|
||||
* @param \DI\Container $container
|
||||
* @param \PhpCsFixer\Finder $finder
|
||||
*/
|
||||
public function __construct(Container $container, Config $config, Finder $finder)
|
||||
{
|
||||
public function __construct(
|
||||
Container $container,
|
||||
Config $config,
|
||||
Finder $finder,
|
||||
TranslatorInterface $translator
|
||||
) {
|
||||
$this->container = $container;
|
||||
$this->config = $config;
|
||||
$this->finder = $finder;
|
||||
$this->translator = $translator;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -50,7 +59,7 @@ class ZipHandler
|
||||
$path = $request->getQueryParams()['zip'];
|
||||
|
||||
if (! $this->config->get('app.zip_downloads', true) || ! realpath($path)) {
|
||||
return $response->withStatus(404, 'File not found');
|
||||
return $response->withStatus(404, $this->translator->trans('error.file_not_found'));
|
||||
}
|
||||
|
||||
$zip = new ZipArchive;
|
||||
|
63
app/src/Providers/TranslationProvider.php
Normal file
63
app/src/Providers/TranslationProvider.php
Normal file
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
|
||||
namespace App\Providers;
|
||||
|
||||
use DI\Container;
|
||||
use Illuminate\Support\Collection;
|
||||
use PHLAK\Config\Config;
|
||||
use RuntimeException;
|
||||
use Symfony\Component\Translation\Loader\YamlFileLoader;
|
||||
use Symfony\Component\Translation\Translator;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
|
||||
class TranslationProvider
|
||||
{
|
||||
/** @const Available translation languages */
|
||||
protected const LANGUAGES = [
|
||||
'de', 'en', 'es', 'fr', 'zh'
|
||||
];
|
||||
|
||||
/** @var Container The applicaiton container */
|
||||
protected $container;
|
||||
|
||||
/** @var Config The application config */
|
||||
protected $config;
|
||||
|
||||
/**
|
||||
* Create a new TranslationProvider object.
|
||||
*
|
||||
* @param \DI\Container $container
|
||||
* @param \PHLAK\Config\Config $config
|
||||
*/
|
||||
public function __construct(Container $container, Config $config)
|
||||
{
|
||||
$this->container = $container;
|
||||
$this->config = $config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize and register the translation component.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __invoke(): void
|
||||
{
|
||||
$language = $this->config->get('app.language', 'en');
|
||||
|
||||
if (! in_array($language, self::LANGUAGES)) {
|
||||
throw new RuntimeException("Invalid language option '{$language}'");
|
||||
}
|
||||
|
||||
$translator = new Translator($language);
|
||||
$translator->addLoader('yaml', new YamlFileLoader());
|
||||
|
||||
Collection::make(self::LANGUAGES)->each(
|
||||
function (string $language) use ($translator): void {
|
||||
$resource = sprintf('app/translations/%s.yaml', $language);
|
||||
$translator->addResource('yaml', $resource, $language);
|
||||
}
|
||||
);
|
||||
|
||||
$this->container->set(TranslatorInterface::class, $translator);
|
||||
}
|
||||
}
|
@@ -22,6 +22,7 @@ class TwigProvider
|
||||
ViewFunctions\Markdown::class,
|
||||
ViewFunctions\ParentDir::class,
|
||||
ViewFunctions\SizeForHumans::class,
|
||||
ViewFunctions\Translate::class,
|
||||
ViewFunctions\Url::class,
|
||||
];
|
||||
|
||||
|
36
app/src/ViewFunctions/Translate.php
Normal file
36
app/src/ViewFunctions/Translate.php
Normal file
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
namespace App\ViewFunctions;
|
||||
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
|
||||
class Translate extends ViewFunction
|
||||
{
|
||||
/** @var string The function name */
|
||||
protected $name = 'translate';
|
||||
|
||||
/** @var TranslatorInterface The application translator */
|
||||
protected $translator;
|
||||
|
||||
/**
|
||||
* Create a new Translate object.
|
||||
*
|
||||
* @param \Symfony\Contracts\Translation\TranslatorInterface $translator
|
||||
*/
|
||||
public function __construct(TranslatorInterface $translator)
|
||||
{
|
||||
$this->translator = $translator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve a translated string by ID.
|
||||
*
|
||||
* @param string $id
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function __invoke(string $id): string
|
||||
{
|
||||
return $this->translator->trans($id);
|
||||
}
|
||||
}
|
19
app/translations/en.yaml
Normal file
19
app/translations/en.yaml
Normal file
@@ -0,0 +1,19 @@
|
||||
home: Home
|
||||
download: Download this Directory
|
||||
search: Search
|
||||
file:
|
||||
name: File Name
|
||||
size: Size
|
||||
date: Date
|
||||
info: File Info
|
||||
powered_by: Powered by
|
||||
scroll_to_top: Scroll to Top
|
||||
|
||||
error:
|
||||
directory_not_found: Directory does not exist
|
||||
file_not_found: File not found
|
||||
file_size_exceeded: File size too large
|
||||
no_results_found: No results found
|
||||
unexpected: An unexpected error occurred
|
||||
|
||||
enable_debugging: Enable debugging for additional information
|
19
app/translations/es.yaml
Normal file
19
app/translations/es.yaml
Normal file
@@ -0,0 +1,19 @@
|
||||
home: Hogar
|
||||
download: Descargar este Directorio
|
||||
search: Buscar
|
||||
file:
|
||||
name: Nombre del Archivo
|
||||
size: Tamaño
|
||||
date: Fecha
|
||||
info: Información del Archivo
|
||||
powered_by: Desarrollado por
|
||||
scroll_to_top: Vuelve al Comienzo
|
||||
|
||||
error:
|
||||
directory_not_found: El directorio no existe
|
||||
file_not_found: Archivo no encontrado
|
||||
file_size_exceeded: Tamaño de archivo demasiado grande
|
||||
no_results_found: No se han encontrado resultados
|
||||
unexpected: Ocurrió un error inesperado
|
||||
|
||||
enable_debugging: Habilite la depuración para obtener información adicional
|
19
app/translations/fr.yaml
Normal file
19
app/translations/fr.yaml
Normal file
@@ -0,0 +1,19 @@
|
||||
home: Accueil
|
||||
download: Téléchargez ce Répertoire
|
||||
search: Chercher
|
||||
file:
|
||||
name: Nom de Fichier
|
||||
size: Taille
|
||||
date: Date
|
||||
info: Informations sur le Fichier
|
||||
powered_by: Alimenté par
|
||||
scroll_to_top: Faire Défiler vers le Haut
|
||||
|
||||
error:
|
||||
directory_not_found: Le répertoire n'existe pas
|
||||
file_not_found: Fichier non trouvé
|
||||
file_size_exceeded: Taille de fichier trop grande
|
||||
no_results_found: Aucun résultat trouvé
|
||||
unexpected: Une erreur inattendue est apparue
|
||||
|
||||
enable_debugging: Activer le débogage pour des informations supplémentaires
|
19
app/translations/zh.yaml
Normal file
19
app/translations/zh.yaml
Normal file
@@ -0,0 +1,19 @@
|
||||
home: 家
|
||||
download: 下载此目录
|
||||
search: 搜索
|
||||
file:
|
||||
name: 文件名
|
||||
size: 尺寸
|
||||
date: 日期
|
||||
info: 文件信息
|
||||
powered_by: 供电
|
||||
scroll_to_top: 滚动到顶部
|
||||
|
||||
error:
|
||||
directory_not_found: 目录不存在
|
||||
file_not_found: 文件未找到
|
||||
file_size_exceeded: 档案太大
|
||||
no_results_found: 未找到结果
|
||||
unexpected: 一个意料之外的问题发生了
|
||||
|
||||
enable_debugging: 启用调试以获取其他信息
|
@@ -18,7 +18,7 @@
|
||||
{% if file.isFile %}
|
||||
<div class="ml-2">
|
||||
<button
|
||||
title="File Info"
|
||||
title="{{ translate('file.info') }}"
|
||||
class="flex justify-center items-center rounded-full p-2 -m-1 md:invisible hover:bg-gray-400 hover:shadow group-hover:visible"
|
||||
v-on:click.prevent="showFileInfo('{{ file.getPathname | escape('js') }}')"
|
||||
>
|
||||
|
@@ -1,7 +1,7 @@
|
||||
<footer class="container border-t-2 border-gray-800 text-center mx-auto px-4 py-8">
|
||||
<div class="flex flex-col justify-center items-center">
|
||||
<p class="mb-4">
|
||||
Powered by <a href="https://www.directorylister.com" class="underline hover:text-blue-700">Directory Lister</a>
|
||||
{{ translate('powered_by') }} <a href="https://www.directorylister.com" class="underline hover:text-blue-700">Directory Lister</a>
|
||||
</p>
|
||||
|
||||
<div class="flex">
|
||||
|
@@ -1,7 +1,9 @@
|
||||
<header id="header" class="bg-blue-600 shadow sticky top-0">
|
||||
<div class="container flex flex-col flex-coljustify-between items-center mx-auto p-4 md:flex-row">
|
||||
<div class="flex-grow font-mono text-white text-sm tracking-tight mb-2 md:my-1">
|
||||
<a href="." class="hover:underline">Home</a>
|
||||
<a href="." class="hover:underline">
|
||||
{{ translate('home') }}
|
||||
</a>
|
||||
|
||||
{% if path %}
|
||||
{% for name, path in breadcrumbs(path) %}
|
||||
@@ -12,14 +14,14 @@
|
||||
|
||||
<div class="flex justify-end items-center">
|
||||
{% if path and config('zip_downloads', true) %}
|
||||
<a href="?zip={{ path }}" title="Download this Directory" class="inline-block text-white mx-2 p-1 hover:text-gray-400">
|
||||
<a href="?zip={{ path }}" title="{{ translate('download') }}" class="inline-block text-white mx-2 p-1 hover:text-gray-400">
|
||||
<i class="fas fa-download fa-lg"></i>
|
||||
</a>
|
||||
{% endif %}
|
||||
|
||||
<form action="." method="get" id="search" class="flex-grow group relative block bg-blue-700 rounded-full shadow-inner">
|
||||
<input v-model="search" ref="searchInput" v-on:focus="$event.target.select()"
|
||||
type="text" name="search" placeholder="Search..." value="{{ search }}"
|
||||
type="text" name="search" placeholder="{{ translate('search') }}..." value="{{ search }}"
|
||||
class="bg-transparent placeholder-gray-900 text-white w-full px-10 py-2"
|
||||
>
|
||||
|
||||
|
@@ -1,8 +1,8 @@
|
||||
<div class="fixed bottom-0 left-0 right-0 pointer-events-none">
|
||||
<div class="container flex justify-end mx-auto px-4 py-10">
|
||||
<button id="scroll-to-top" ref="scrollToTop"
|
||||
<button id="scroll-to-top" ref="scrollToTop" title="{{ translate('scroll_to_top') }}"
|
||||
class="flex justify-center items-center w-12 h-12 right-0 rounded-full shadow-lg bg-blue-600 text-white cursor-pointer pointer-events-auto hover:bg-blue-700 hidden"
|
||||
onclick="window.scrollTo({ top: 0, left: 0, behavior: 'smooth' });" title="Scroll to Top"
|
||||
onclick="window.scrollTo({ top: 0, left: 0, behavior: 'smooth' });"
|
||||
>
|
||||
<i class="fas fa-arrow-up fa-lg"></i>
|
||||
</button>
|
||||
|
@@ -7,15 +7,15 @@
|
||||
<div class="my-4">
|
||||
<div class="flex justify-between font-bold p-4">
|
||||
<div class="flex-grow font-mono mr-2">
|
||||
File Name
|
||||
{{ translate('file.name') }}
|
||||
</div>
|
||||
|
||||
<div class="font-mono text-right w-1/6 mx-2 hidden sm:block">
|
||||
Size
|
||||
{{ translate('file.size') }}
|
||||
</div>
|
||||
|
||||
<div class="font-mono text-right w-1/4 ml-2 hidden sm:block">
|
||||
Date
|
||||
{{ translate('file.date') }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@@ -23,6 +23,7 @@
|
||||
"slim/slim": "^4.3",
|
||||
"slim/twig-view": "^3.0",
|
||||
"symfony/finder": "^5.0",
|
||||
"symfony/translation": "^5.0",
|
||||
"tightenco/collect": "^6.4",
|
||||
"vlucas/phpdotenv": "^4.0"
|
||||
},
|
||||
|
136
composer.lock
generated
136
composer.lock
generated
@@ -4,7 +4,7 @@
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "1a4f0a5fb5a91dc494cb5479886f6001",
|
||||
"content-hash": "ec21efdea1e0689436e9653f81e1c18c",
|
||||
"packages": [
|
||||
{
|
||||
"name": "erusev/parsedown",
|
||||
@@ -1690,6 +1690,140 @@
|
||||
],
|
||||
"time": "2020-01-13T11:15:53+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/translation",
|
||||
"version": "v5.0.4",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/translation.git",
|
||||
"reference": "28e1054f1ea26c63762d9260c37cb1056ea62dbb"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/translation/zipball/28e1054f1ea26c63762d9260c37cb1056ea62dbb",
|
||||
"reference": "28e1054f1ea26c63762d9260c37cb1056ea62dbb",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.2.5",
|
||||
"symfony/polyfill-mbstring": "~1.0",
|
||||
"symfony/translation-contracts": "^2"
|
||||
},
|
||||
"conflict": {
|
||||
"symfony/config": "<4.4",
|
||||
"symfony/dependency-injection": "<5.0",
|
||||
"symfony/http-kernel": "<5.0",
|
||||
"symfony/twig-bundle": "<5.0",
|
||||
"symfony/yaml": "<4.4"
|
||||
},
|
||||
"provide": {
|
||||
"symfony/translation-implementation": "2.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"psr/log": "~1.0",
|
||||
"symfony/config": "^4.4|^5.0",
|
||||
"symfony/console": "^4.4|^5.0",
|
||||
"symfony/dependency-injection": "^5.0",
|
||||
"symfony/finder": "^4.4|^5.0",
|
||||
"symfony/http-kernel": "^5.0",
|
||||
"symfony/intl": "^4.4|^5.0",
|
||||
"symfony/service-contracts": "^1.1.2|^2",
|
||||
"symfony/yaml": "^4.4|^5.0"
|
||||
},
|
||||
"suggest": {
|
||||
"psr/log-implementation": "To use logging capability in translator",
|
||||
"symfony/config": "",
|
||||
"symfony/yaml": ""
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "5.0-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Symfony\\Component\\Translation\\": ""
|
||||
},
|
||||
"exclude-from-classmap": [
|
||||
"/Tests/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Fabien Potencier",
|
||||
"email": "fabien@symfony.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Symfony Translation Component",
|
||||
"homepage": "https://symfony.com",
|
||||
"time": "2020-01-21T08:40:24+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/translation-contracts",
|
||||
"version": "v2.0.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/translation-contracts.git",
|
||||
"reference": "8cc682ac458d75557203b2f2f14b0b92e1c744ed"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/translation-contracts/zipball/8cc682ac458d75557203b2f2f14b0b92e1c744ed",
|
||||
"reference": "8cc682ac458d75557203b2f2f14b0b92e1c744ed",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.2.5"
|
||||
},
|
||||
"suggest": {
|
||||
"symfony/translation-implementation": ""
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "2.0-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Symfony\\Contracts\\Translation\\": ""
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Nicolas Grekas",
|
||||
"email": "p@tchwork.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Generic abstractions related to translation",
|
||||
"homepage": "https://symfony.com",
|
||||
"keywords": [
|
||||
"abstractions",
|
||||
"contracts",
|
||||
"decoupling",
|
||||
"interfaces",
|
||||
"interoperability",
|
||||
"standards"
|
||||
],
|
||||
"time": "2019-11-18T17:27:11+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/var-dumper",
|
||||
"version": "v5.0.4",
|
||||
|
@@ -11,10 +11,19 @@ use Tests\TestCase;
|
||||
|
||||
class ErrorHandlerTest extends TestCase
|
||||
{
|
||||
public function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->container->call(TwigProvider::class);
|
||||
}
|
||||
|
||||
public function test_it_returns_an_error(): void
|
||||
{
|
||||
$this->container->call(TwigProvider::class);
|
||||
$errorHandler = new ErrorHandler($this->container->get(Twig::class));
|
||||
$errorHandler = new ErrorHandler(
|
||||
$this->container->get(Twig::class),
|
||||
$this->translator
|
||||
);
|
||||
|
||||
$response = $errorHandler(
|
||||
$this->createMock(Request::class),
|
||||
@@ -32,8 +41,10 @@ class ErrorHandlerTest extends TestCase
|
||||
|
||||
public function test_it_returns_an_error_for_a_json_request(): void
|
||||
{
|
||||
$this->container->call(TwigProvider::class);
|
||||
$errorHandler = new ErrorHandler($this->container->get(Twig::class));
|
||||
$errorHandler = new ErrorHandler(
|
||||
$this->container->get(Twig::class),
|
||||
$this->translator
|
||||
);
|
||||
|
||||
$request = $this->createMock(Request::class);
|
||||
$request->expects($this->once())->method('getHeaderLine')->willReturn(
|
||||
@@ -50,7 +61,7 @@ class ErrorHandlerTest extends TestCase
|
||||
|
||||
$this->assertEquals(500, $response->getStatusCode());
|
||||
$this->assertEquals('application/json', $response->getHeaderLine('Content-Type'));
|
||||
$this->assertEquals('An unexpected error occured', json_decode(
|
||||
$this->assertEquals('An unexpected error occurred', json_decode(
|
||||
(string) $response->getBody()
|
||||
)->error->message);
|
||||
}
|
||||
|
@@ -28,7 +28,8 @@ class DirectoryHandlerTest extends TestCase
|
||||
$controller = new DirectoryHandler(
|
||||
$this->config,
|
||||
new Finder,
|
||||
$this->container->get(Twig::class)
|
||||
$this->container->get(Twig::class),
|
||||
$this->translator
|
||||
);
|
||||
|
||||
chdir($this->filePath('.'));
|
||||
@@ -53,7 +54,8 @@ class DirectoryHandlerTest extends TestCase
|
||||
$controller = new DirectoryHandler(
|
||||
$this->config,
|
||||
new Finder,
|
||||
$this->container->get(Twig::class)
|
||||
$this->container->get(Twig::class),
|
||||
$this->translator
|
||||
);
|
||||
|
||||
$request = $this->createMock(Request::class);
|
||||
@@ -73,7 +75,8 @@ class DirectoryHandlerTest extends TestCase
|
||||
$controller = new DirectoryHandler(
|
||||
$this->config,
|
||||
new Finder,
|
||||
$this->container->get(Twig::class)
|
||||
$this->container->get(Twig::class),
|
||||
$this->translator
|
||||
);
|
||||
|
||||
$request = $this->createMock(Request::class);
|
||||
|
@@ -12,7 +12,7 @@ class FileInfoHandlerTest extends TestCase
|
||||
{
|
||||
public function test_it_can_return_a_successful_response(): void
|
||||
{
|
||||
$handler = new FileInfoHandler($this->container, $this->config);
|
||||
$handler = new FileInfoHandler($this->container, $this->config, $this->translator);
|
||||
|
||||
$request = $this->createMock(Request::class);
|
||||
$request->method('getQueryParams')->willReturn(['info' => 'README.md']);
|
||||
@@ -32,7 +32,7 @@ class FileInfoHandlerTest extends TestCase
|
||||
|
||||
public function test_it_can_return_a_not_found_response(): void
|
||||
{
|
||||
$handler = new FileInfoHandler($this->container, $this->config);
|
||||
$handler = new FileInfoHandler($this->container, $this->config, $this->translator);
|
||||
|
||||
$request = $this->createMock(Request::class);
|
||||
$request->method('getQueryParams')->willReturn(['info' => 'not_a_file.test']);
|
||||
@@ -46,7 +46,7 @@ class FileInfoHandlerTest extends TestCase
|
||||
public function test_it_returns_an_error_when_file_size_is_too_large(): void
|
||||
{
|
||||
$this->config->set('app.max_hash_size', 10);
|
||||
$handler = new FileInfoHandler($this->container, $this->config);
|
||||
$handler = new FileInfoHandler($this->container, $this->config, $this->translator);
|
||||
|
||||
$request = $this->createMock(Request::class);
|
||||
$request->method('getQueryParams')->willReturn(['info' => 'README.md']);
|
||||
|
@@ -13,7 +13,7 @@ class ZipHandlerTest extends TestCase
|
||||
{
|
||||
public function test_it_returns_a_successful_response_for_a_zip_request(): void
|
||||
{
|
||||
$handler = new ZipHandler($this->container, $this->config, new Finder);
|
||||
$handler = new ZipHandler($this->container, $this->config, new Finder, $this->translator);
|
||||
|
||||
$request = $this->createMock(Request::class);
|
||||
$request->method('getQueryParams')->willReturn(['zip' => 'subdir']);
|
||||
@@ -30,7 +30,7 @@ class ZipHandlerTest extends TestCase
|
||||
|
||||
public function test_it_returns_a_404_error_when_not_found(): void
|
||||
{
|
||||
$handler = new ZipHandler($this->container, $this->config, new Finder);
|
||||
$handler = new ZipHandler($this->container, $this->config, new Finder, $this->translator);
|
||||
|
||||
$request = $this->createMock(Request::class);
|
||||
$request->method('getQueryParams')->willReturn(['zip' => '404']);
|
||||
@@ -45,7 +45,7 @@ class ZipHandlerTest extends TestCase
|
||||
public function test_it_returns_a_404_error_when_disabled_via_config(): void
|
||||
{
|
||||
$this->config->set('app.zip_downloads', false);
|
||||
$handler = new ZipHandler($this->container, $this->config, new Finder);
|
||||
$handler = new ZipHandler($this->container, $this->config, new Finder, $this->translator);
|
||||
|
||||
$request = $this->createMock(Request::class);
|
||||
$request->method('getQueryParams')->willReturn(['zip' => 'subdir']);
|
||||
|
31
tests/Providers/TranslationProviderTest.php
Normal file
31
tests/Providers/TranslationProviderTest.php
Normal file
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Providers;
|
||||
|
||||
use App\Providers\TranslationProvider;
|
||||
use RuntimeException;
|
||||
use Symfony\Component\Translation\MessageCatalogue;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
use Tests\TestCase;
|
||||
|
||||
class TranslationProviderTest extends TestCase
|
||||
{
|
||||
public function test_it_registers_the_translation_component(): void
|
||||
{
|
||||
(new TranslationProvider($this->container, $this->config))();
|
||||
|
||||
$translator = $this->container->get(TranslatorInterface::class);
|
||||
|
||||
$this->assertEquals('en', $translator->getLocale());
|
||||
$this->assertInstanceOf(MessageCatalogue::class, $translator->getCatalogue('en'));
|
||||
$this->assertInstanceOf(MessageCatalogue::class, $translator->getCatalogue('fr'));
|
||||
}
|
||||
|
||||
public function test_it_throws_an_exception_for_an_invalid_language(): void
|
||||
{
|
||||
$this->expectException(RuntimeException::class);
|
||||
|
||||
$this->config->set('app.language', 'xx');
|
||||
(new TranslationProvider($this->container, $this->config))();
|
||||
}
|
||||
}
|
@@ -5,6 +5,9 @@ namespace Tests;
|
||||
use DI\Container;
|
||||
use PHLAK\Config\Config;
|
||||
use PHPUnit\Framework\TestCase as PHPUnitTestCase;
|
||||
use Symfony\Component\Translation\Loader\ArrayLoader;
|
||||
use Symfony\Component\Translation\Translator;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
|
||||
class TestCase extends PHPUnitTestCase
|
||||
{
|
||||
@@ -14,6 +17,9 @@ class TestCase extends PHPUnitTestCase
|
||||
/** @var Config The test config */
|
||||
protected $config;
|
||||
|
||||
/** @var TranslatorInterface Test translator */
|
||||
protected $translator;
|
||||
|
||||
/** @var string Path to test files directory */
|
||||
protected $testFilesPath = __DIR__ . '/_files';
|
||||
|
||||
@@ -28,6 +34,8 @@ class TestCase extends PHPUnitTestCase
|
||||
|
||||
$this->config = new Config([
|
||||
'app' => [
|
||||
'debug' => false,
|
||||
'language' => 'en',
|
||||
'dark_mode' => false,
|
||||
'display_readmes' => true,
|
||||
'zip_downloads' => true,
|
||||
@@ -43,9 +51,34 @@ class TestCase extends PHPUnitTestCase
|
||||
]
|
||||
]);
|
||||
|
||||
$this->translator = new Translator('en');
|
||||
$this->translator->addLoader('array', new ArrayLoader);
|
||||
$this->translator->addResource('array', [
|
||||
'home' => 'Home',
|
||||
'download' => 'Download this Directory',
|
||||
'search' => 'Search',
|
||||
'file' => [
|
||||
'name' => 'File Name',
|
||||
'size' => 'Size',
|
||||
'date' => 'Date',
|
||||
'info' => 'File Info',
|
||||
'powered_by' => 'Powered by',
|
||||
'scroll_to_top' => 'Scroll to Top',
|
||||
],
|
||||
'error' => [
|
||||
'directory_not_found' => 'Directory does not exist',
|
||||
'file_not_found' => 'File not found',
|
||||
'file_size_exceeded' => 'File size too large',
|
||||
'no_results_found' => 'No results found',
|
||||
'unexpected' => 'An unexpected error occurred',
|
||||
],
|
||||
'enable_debugging' => 'Enable debugging for additional information',
|
||||
], 'en');
|
||||
|
||||
$this->container = new Container();
|
||||
$this->container->set('base_path', $this->testFilesPath);
|
||||
$this->container->set(Config::class, $this->config);
|
||||
$this->container->set(TranslatorInterface::class, $this->translator);
|
||||
}
|
||||
|
||||
/**
|
||||
|
45
tests/ViewFunctions/TranslateTest.php
Normal file
45
tests/ViewFunctions/TranslateTest.php
Normal file
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\ViewFunctions;
|
||||
|
||||
use App\ViewFunctions\Translate;
|
||||
use Symfony\Component\Translation\Loader\ArrayLoader;
|
||||
use Symfony\Component\Translation\Translator;
|
||||
use Tests\TestCase;
|
||||
|
||||
class TranslateTest extends TestCase
|
||||
{
|
||||
/** @var Translator Translator component */
|
||||
protected $tranlator;
|
||||
|
||||
public function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->translator = new Translator('en');
|
||||
$this->translator->addLoader('array', new ArrayLoader);
|
||||
$this->translator->addResource('array', [
|
||||
'foo' => 'Foo', 'bar' => ['baz' => 'Bar Baz'],
|
||||
], 'en');
|
||||
$this->translator->addResource('array', [
|
||||
'foo' => 'Le Foo', 'bar' => ['baz' => 'Le Bar Baz'],
|
||||
], 'fr');
|
||||
}
|
||||
|
||||
public function test_it_can_get_a_translation_for_the_defualt_locale(): void
|
||||
{
|
||||
$translate = new Translate($this->translator);
|
||||
|
||||
$this->assertEquals('Foo', $translate('foo'));
|
||||
$this->assertEquals('Bar Baz', $translate('bar.baz'));
|
||||
}
|
||||
|
||||
public function test_it_can_get_a_translation_for_an_alternative_locale(): void
|
||||
{
|
||||
$this->translator->setLocale('fr');
|
||||
$translate = new Translate($this->translator);
|
||||
|
||||
$this->assertEquals('Le Foo', $translate('foo'));
|
||||
$this->assertEquals('Le Bar Baz', $translate('bar.baz'));
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user