diff --git a/.env.dist b/.env.dist
index d6271d57..726635ba 100644
--- a/.env.dist
+++ b/.env.dist
@@ -3,6 +3,7 @@ APP_ENV=
SHORTENED_URL_SCHEMA=
SHORTENED_URL_HOSTNAME=
SHORTCODE_CHARS=
+DEFAULT_LOCALE=
# Database
DB_USER=
diff --git a/composer.json b/composer.json
index 0211ed05..b9be6c6d 100644
--- a/composer.json
+++ b/composer.json
@@ -21,10 +21,11 @@
"zendframework/zend-servicemanager": "^3.0",
"zendframework/zend-paginator": "^2.6",
"zendframework/zend-config": "^2.6",
+ "zendframework/zend-i18n": "^2.7",
"mtymek/expressive-config-manager": "^0.4",
+ "acelaya/zsm-annotated-services": "^0.2.0",
"doctrine/orm": "^2.5",
"guzzlehttp/guzzle": "^6.2",
- "acelaya/zsm-annotated-services": "^0.2.0",
"symfony/console": "^3.0"
},
"require-dev": {
diff --git a/config/autoload/translator.global.php b/config/autoload/translator.global.php
new file mode 100644
index 00000000..e3730927
--- /dev/null
+++ b/config/autoload/translator.global.php
@@ -0,0 +1,8 @@
+ [
+ 'locale' => getenv('DEFAULT_LOCALE') ?: 'en',
+ ],
+
+];
diff --git a/module/CLI/config/translator.config.php b/module/CLI/config/translator.config.php
new file mode 100644
index 00000000..ae120db3
--- /dev/null
+++ b/module/CLI/config/translator.config.php
@@ -0,0 +1,14 @@
+ [
+ 'translation_file_patterns' => [
+ [
+ 'type' => 'gettext',
+ 'base_dir' => __DIR__ . '/../lang',
+ 'pattern' => '%s.mo',
+ ],
+ ],
+ ],
+
+];
diff --git a/module/CLI/lang/es.mo b/module/CLI/lang/es.mo
new file mode 100644
index 00000000..08f58bd9
Binary files /dev/null and b/module/CLI/lang/es.mo differ
diff --git a/module/CLI/lang/es.po b/module/CLI/lang/es.po
new file mode 100644
index 00000000..896f2965
--- /dev/null
+++ b/module/CLI/lang/es.po
@@ -0,0 +1,40 @@
+msgid ""
+msgstr ""
+"Project-Id-Version: Shlink 1.0\n"
+"POT-Creation-Date: 2016-07-21 15:05+0200\n"
+"PO-Revision-Date: 2016-07-21 15:08+0200\n"
+"Last-Translator: \n"
+"Language-Team: \n"
+"Language: es_ES\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: Poedit 1.8.7.1\n"
+"X-Poedit-Basepath: ..\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Poedit-SourceCharset: UTF-8\n"
+"X-Poedit-KeywordsList: translate;translatePlural\n"
+"X-Poedit-SearchPath-0: src\n"
+"X-Poedit-SearchPath-1: config\n"
+
+msgid "Generates a shortcode for provided URL and returns the short URL"
+msgstr "Genera un código corto para la URL proporcionada y devuelve la URL acortada"
+
+msgid "The long URL to parse"
+msgstr "La URL larga a procesar"
+
+msgid "A long URL was not provided. Which URL do you want to shorten?:"
+msgstr "No se ha proporcionado una URL larga. ¿Qué URL deseas acortar?"
+
+msgid "A URL was not provided!"
+msgstr "¡No se ha proporcionado una URL!"
+
+msgid "Processed URL:"
+msgstr "URL procesada:"
+
+msgid "Generated URL:"
+msgstr "URL generada:"
+
+#, php-format
+msgid "Provided URL \"%s\" is invalid. Try with a different one."
+msgstr "La URL proporcionada \"%s\" e inválida. Prueba con una diferente."
diff --git a/module/CLI/src/Command/GenerateShortcodeCommand.php b/module/CLI/src/Command/GenerateShortcodeCommand.php
index 91cbd228..0a0af9eb 100644
--- a/module/CLI/src/Command/GenerateShortcodeCommand.php
+++ b/module/CLI/src/Command/GenerateShortcodeCommand.php
@@ -12,6 +12,7 @@ use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Question\Question;
use Zend\Diactoros\Uri;
+use Zend\I18n\Translator\TranslatorInterface;
class GenerateShortcodeCommand extends Command
{
@@ -23,26 +24,37 @@ class GenerateShortcodeCommand extends Command
* @var array
*/
private $domainConfig;
+ /**
+ * @var TranslatorInterface
+ */
+ private $translator;
/**
* GenerateShortcodeCommand constructor.
* @param UrlShortenerInterface|UrlShortener $urlShortener
+ * @param TranslatorInterface $translator
* @param array $domainConfig
*
- * @Inject({UrlShortener::class, "config.url_shortener.domain"})
+ * @Inject({UrlShortener::class, "translator", "config.url_shortener.domain"})
*/
- public function __construct(UrlShortenerInterface $urlShortener, array $domainConfig)
- {
- parent::__construct(null);
+ public function __construct(
+ UrlShortenerInterface $urlShortener,
+ TranslatorInterface $translator,
+ array $domainConfig
+ ) {
$this->urlShortener = $urlShortener;
+ $this->translator = $translator;
$this->domainConfig = $domainConfig;
+ parent::__construct(null);
}
public function configure()
{
$this->setName('shortcode:generate')
- ->setDescription('Generates a shortcode for provided URL and returns the short URL')
- ->addArgument('longUrl', InputArgument::REQUIRED, 'The long URL to parse');
+ ->setDescription(
+ $this->translator->translate('Generates a shortcode for provided URL and returns the short URL')
+ )
+ ->addArgument('longUrl', InputArgument::REQUIRED, $this->translator->translate('The long URL to parse'));
}
public function interact(InputInterface $input, OutputInterface $output)
@@ -54,9 +66,10 @@ class GenerateShortcodeCommand extends Command
/** @var QuestionHelper $helper */
$helper = $this->getHelper('question');
- $question = new Question(
- 'A long URL was not provided. Which URL do you want to shorten?: '
- );
+ $question = new Question(sprintf(
+ '%s ',
+ $this->translator->translate('A long URL was not provided. Which URL do you want to shorten?:')
+ ));
$longUrl = $helper->ask($input, $output, $question);
if (! empty($longUrl)) {
@@ -70,7 +83,7 @@ class GenerateShortcodeCommand extends Command
try {
if (! isset($longUrl)) {
- $output->writeln('A URL was not provided!');
+ $output->writeln(sprintf('%s', $this->translator->translate('A URL was not provided!')));
return;
}
@@ -80,13 +93,16 @@ class GenerateShortcodeCommand extends Command
->withHost($this->domainConfig['hostname']);
$output->writeln([
- sprintf('Processed URL %s', $longUrl),
- sprintf('Generated URL %s', $shortUrl),
+ sprintf('%s %s', $this->translator->translate('Processed URL:'), $longUrl),
+ sprintf('%s %s', $this->translator->translate('Generated URL:'), $shortUrl),
]);
} catch (InvalidUrlException $e) {
- $output->writeln(
- sprintf('Provided URL "%s" is invalid. Try with a different one.', $longUrl)
- );
+ $output->writeln(sprintf(
+ '' . $this->translator->translate(
+ 'Provided URL "%s" is invalid. Try with a different one.'
+ ) . '',
+ $longUrl
+ ));
}
}
}
diff --git a/module/Common/config/services.config.php b/module/Common/config/services.config.php
index 838b7896..1423b543 100644
--- a/module/Common/config/services.config.php
+++ b/module/Common/config/services.config.php
@@ -4,7 +4,10 @@ use Doctrine\Common\Cache\Cache;
use Doctrine\ORM\EntityManager;
use Shlinkio\Shlink\Common\Factory\CacheFactory;
use Shlinkio\Shlink\Common\Factory\EntityManagerFactory;
+use Shlinkio\Shlink\Common\Factory\TranslatorFactory;
use Shlinkio\Shlink\Common\Service\IpLocationResolver;
+use Shlinkio\Shlink\Common\Twig\Extension\TranslatorExtension;
+use Zend\I18n\Translator\Translator;
use Zend\ServiceManager\Factory\InvokableFactory;
return [
@@ -15,10 +18,13 @@ return [
GuzzleHttp\Client::class => InvokableFactory::class,
Cache::class => CacheFactory::class,
IpLocationResolver::class => AnnotatedFactory::class,
+ Translator::class => TranslatorFactory::class,
+ TranslatorExtension::class => AnnotatedFactory::class,
],
'aliases' => [
'em' => EntityManager::class,
'httpClient' => GuzzleHttp\Client::class,
+ 'translator' => Translator::class,
AnnotatedFactory::CACHE_SERVICE => Cache::class,
],
],
diff --git a/module/Common/config/templates.config.php b/module/Common/config/templates.config.php
new file mode 100644
index 00000000..903c1e8c
--- /dev/null
+++ b/module/Common/config/templates.config.php
@@ -0,0 +1,12 @@
+ [
+ 'extensions' => [
+ TranslatorExtension::class,
+ ],
+ ],
+
+];
diff --git a/module/Common/src/Factory/TranslatorFactory.php b/module/Common/src/Factory/TranslatorFactory.php
new file mode 100644
index 00000000..e41ba2fc
--- /dev/null
+++ b/module/Common/src/Factory/TranslatorFactory.php
@@ -0,0 +1,30 @@
+get('config');
+ return Translator::factory(isset($config['translator']) ? $config['translator'] : []);
+ }
+}
diff --git a/module/Common/src/Twig/Extension/TranslatorExtension.php b/module/Common/src/Twig/Extension/TranslatorExtension.php
new file mode 100644
index 00000000..48ee3f11
--- /dev/null
+++ b/module/Common/src/Twig/Extension/TranslatorExtension.php
@@ -0,0 +1,75 @@
+translator = $translator;
+ }
+
+ /**
+ * Returns the name of the extension.
+ *
+ * @return string The extension name
+ */
+ public function getName()
+ {
+ return __CLASS__;
+ }
+
+ public function getFunctions()
+ {
+ return [
+ new \Twig_SimpleFunction('translate', [$this, 'translate']),
+ new \Twig_SimpleFunction('translate_plural', [$this, 'translatePlural']),
+ ];
+ }
+
+ /**
+ * Translate a message.
+ *
+ * @param string $message
+ * @param string $textDomain
+ * @param string $locale
+ * @return string
+ */
+ public function translate($message, $textDomain = 'default', $locale = null)
+ {
+ return $this->translator->translate($message, $textDomain, $locale);
+ }
+
+ /**
+ * Translate a plural message.
+ *
+ * @param string $singular
+ * @param string $plural
+ * @param int $number
+ * @param string $textDomain
+ * @param string|null $locale
+ * @return string
+ */
+ public function translatePlural(
+ $singular,
+ $plural,
+ $number,
+ $textDomain = 'default',
+ $locale = null
+ ) {
+ $this->translator->translatePlural($singular, $plural, $number, $textDomain, $locale);
+ }
+}