Skip to content

Commit

Permalink
Merge pull request #996 from spiral/feature/translation-directories
Browse files Browse the repository at this point in the history
  • Loading branch information
spiralbot committed Sep 20, 2023
1 parent f9e9c27 commit 1b9bef0
Show file tree
Hide file tree
Showing 9 changed files with 214 additions and 17 deletions.
48 changes: 38 additions & 10 deletions src/Catalogue/CatalogueLoader.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,25 +23,29 @@ public function hasLocale(string $locale): bool
{
$locale = \preg_replace('/[^a-zA-Z_]/', '', \mb_strtolower($locale));

return \is_dir($this->config->getLocaleDirectory($locale));
foreach ($this->getDirectories() as $directory) {
if (\is_dir($this->config->getLocaleDirectory($locale, $directory))) {
return true;
}
}

return false;
}

public function getLocales(): array
{
if (!\is_dir($this->config->getLocalesDirectory())) {
$directories = $this->getDirectories();
if ($directories === []) {
return [];
}

$finder = new Finder();
$finder->in($this->config->getLocalesDirectory())->directories();

$locales = [];

foreach ($finder->directories() as $directory) {
foreach ($finder->in($directories)->directories() as $directory) {
$locales[] = $directory->getFilename();
}

return $locales;
return \array_unique($locales);
}

public function loadCatalogue(string $locale): CatalogueInterface
Expand All @@ -53,10 +57,15 @@ public function loadCatalogue(string $locale): CatalogueInterface
return $catalogue;
}

$finder = new Finder();
$finder->in($this->config->getLocaleDirectory($locale));
$directories = [];
foreach ($this->getDirectories() as $directory) {
if (\is_dir($this->config->getLocaleDirectory($locale, $directory))) {
$directories[] = $this->config->getLocaleDirectory($locale, $directory);
}
}

foreach ($finder->getIterator() as $file) {
$finder = new Finder();
foreach ($finder->in($directories)->files() as $file) {
$this->getLogger()->info(
\sprintf(
"found locale domain file '%s'",
Expand Down Expand Up @@ -91,4 +100,23 @@ public function loadCatalogue(string $locale): CatalogueInterface

return $catalogue;
}

/**
* @return array<array-key, non-empty-string>
*/
private function getDirectories(): array
{
$directories = [];
if (\is_dir($this->config->getLocalesDirectory())) {
$directories[] = $this->config->getLocalesDirectory();
}

foreach ($this->config->getDirectories() as $directory) {
if (\is_dir($directory)) {
$directories[] = $directory;
}
}

return $directories;
}
}
35 changes: 31 additions & 4 deletions src/Config/TranslatorConfig.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,9 @@ final class TranslatorConfig extends InjectableConfig
* @var array{
* locale: string,
* fallbackLocale?: string,
* directory: string,
* localesDirectory?: string,
* directory: non-empty-string,
* directories: array<array-key, non-empty-string>,
* localesDirectory?: non-empty-string,
* registerMessages?: bool,
* cacheLocales: bool,
* autoRegister: bool,
Expand All @@ -33,6 +34,7 @@ final class TranslatorConfig extends InjectableConfig
protected array $config = [
'locale' => '',
'directory' => '',
'directories' => [],
'cacheLocales' => true,
'autoRegister' => true,
'domains' => [],
Expand Down Expand Up @@ -71,14 +73,39 @@ public function isAutoRegisterMessages(): bool
return !empty($this->config['autoRegister']) || !empty($this->config['registerMessages']);
}

/**
* Returns application locales directory.
*
* @return non-empty-string
*/
public function getLocalesDirectory(): string
{
return $this->config['localesDirectory'] ?? $this->config['directory'] ?? '';
}

public function getLocaleDirectory(string $locale): string
/**
* Returns additional locales directories.
*
* @return array<array-key, non-empty-string>
*/
public function getDirectories(): array
{
return $this->getLocalesDirectory() . $locale . '/';
return $this->config['directories'] ?? [];
}

/**
* @param non-empty-string $locale
* @param non-empty-string|null $directory
*
* @return non-empty-string
*/
public function getLocaleDirectory(string $locale, ?string $directory = null): string
{
if ($directory !== null) {
return \rtrim($directory, '/') . '/' . $locale . '/';
}

return \trim($this->getLocalesDirectory(), '/') . '/' . $locale . '/';
}

/**
Expand Down
35 changes: 35 additions & 0 deletions tests/ConfigTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,27 @@ public function testLocaleDirectoryShort(): void
$this->assertSame('directory/ru/', $config->getLocaleDirectory('ru'));
}

public function testLocaleDirectoryWithoutSlash(): void
{
$config = new TranslatorConfig([
'localesDirectory' => 'directory'
]);
$this->assertSame('directory/en/', $config->getLocaleDirectory('en'));

$config = new TranslatorConfig([
'directory' => 'directory'
]);
$this->assertSame('directory/en/', $config->getLocaleDirectory('en'));
}

public function testLocaleDirectoryWithDirectoryParam(): void
{
$config = new TranslatorConfig();

$this->assertSame('directory/en/', $config->getLocaleDirectory('en', 'directory'));
$this->assertSame('directory/en/', $config->getLocaleDirectory('en', 'directory/'));
}

public function testDomains(): void
{
$config = new TranslatorConfig([
Expand Down Expand Up @@ -145,4 +166,18 @@ public function testGetDumper(): void

$this->assertInstanceOf(DumperInterface::class, $config->getDumper('po'));
}

public function testGetDirectories(): void
{
$config = new TranslatorConfig();
$this->assertSame([], $config->getDirectories());

$config = new TranslatorConfig([
'directories' => [
'foo',
'bar/'
]
]);
$this->assertSame(['foo', 'bar/'], $config->getDirectories());
}
}
72 changes: 72 additions & 0 deletions tests/LoaderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,18 @@ public function testHasLocale(): void

$this->assertTrue($loader->hasLocale('ru'));
$this->assertTrue($loader->hasLocale('RU'));
$this->assertFalse($loader->hasLocale('fr'));
$this->assertFalse($loader->hasLocale('FR'));

$loader = new CatalogueLoader(new TranslatorConfig([
'directory' => __DIR__ . '/fixtures/locales/',
'directories' => [__DIR__ . '/fixtures/additional'],
]));

$this->assertTrue($loader->hasLocale('ru'));
$this->assertTrue($loader->hasLocale('RU'));
$this->assertTrue($loader->hasLocale('fr'));
$this->assertTrue($loader->hasLocale('FR'));
}

public function testGetLocales(): void
Expand All @@ -39,6 +51,21 @@ public function testGetLocales(): void
$this->assertSame($shouldBe, $compared);
}

public function testGetLocalesWithAdditionalDirectories(): void
{
$loader = new CatalogueLoader(new TranslatorConfig([
'directory' => __DIR__ . '/fixtures/locales/',
'directories' => [__DIR__ . '/fixtures/additional'],
]));

$compared = $loader->getLocales();
$shouldBe = ['en', 'ru', 'fr'];
sort($shouldBe);
sort($compared);

$this->assertSame($shouldBe, $compared);
}

public function testLoadCatalogue(): void
{
$loader = new CatalogueLoader(new TranslatorConfig([
Expand Down Expand Up @@ -77,6 +104,51 @@ public function testLoadCatalogue(): void
'Twig версия',
$mc->get('Twig Version', 'views')
);

$this->assertFalse($loader->hasLocale('fr'));
}

public function testLoadCatalogueWithAdditionalDirectories(): void
{
$loader = new CatalogueLoader(new TranslatorConfig([
'directory' => __DIR__ . '/fixtures/locales/',
'directories' => [__DIR__ . '/fixtures/additional'],
'loaders' => [
'php' => PhpFileLoader::class,
'po' => PoFileLoader::class,
],
]));

$catalogue = $loader->loadCatalogue('fr');
$mc = $catalogue->toMessageCatalogue();
$this->assertTrue($mc->has('Welcome To Spiral', 'views'));
$this->assertSame(
'Bienvenue à Spirale',
$mc->get('Welcome To Spiral', 'views')
);

$this->assertTrue($loader->hasLocale('fr'));
$this->assertTrue($loader->hasLocale('FR'));
$this->assertTrue($loader->hasLocale('ru'));
$this->assertTrue($loader->hasLocale('RU'));
}

public function testApplicationTranslationShouldOverrideAdditionalTranslations(): void
{
$loader = new CatalogueLoader(new TranslatorConfig([
'directory' => __DIR__ . '/fixtures/locales/',
'directories' => [__DIR__ . '/fixtures/additional'],
'loaders' => [
'php' => PhpFileLoader::class,
'po' => PoFileLoader::class,
],
]));

$catalogue = $loader->loadCatalogue('ru');
$mc = $catalogue->toMessageCatalogue();

$this->assertTrue($mc->has('should_be_override'));
$this->assertSame('changed by application translation', $mc->get('should_be_override'));
}

public function testLoadCatalogueNoLoader(): void
Expand Down
6 changes: 4 additions & 2 deletions tests/ManagerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,8 @@ public function testCatalogue(): void
'ru',
[
'messages' => [
'message' => 'translation'
'message' => 'translation',
'should_be_override' => 'changed by application translation'
],
'views' => [
'Welcome To Spiral' => 'Добро пожаловать в Spiral Framework',
Expand All @@ -91,7 +92,8 @@ public function testCatalogue(): void
'ru',
[
'messages' => [
'message' => 'new message'
'message' => 'new message',
'should_be_override' => 'changed by application translation'
],
'views' => [
'Welcome To Spiral' => 'Добро пожаловать в Spiral Framework',
Expand Down
7 changes: 7 additions & 0 deletions tests/fixtures/additional/fr/messages.fr.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?php

declare(strict_types=1);

return [
'message' => 'translation',
];
18 changes: 18 additions & 0 deletions tests/fixtures/additional/fr/views.fr.po
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
msgid ""
msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: fr\n"
"Project-Id-Version: \n"
"POT-Creation-Date: \n"
"PO-Revision-Date: \n"
"Last-Translator: \n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"X-Generator: Poedit 1.8.6\n"

msgid "Welcome To Spiral"
msgstr "Bienvenue à Spirale"

msgid "Twig Version"
msgstr "Twig Version"
7 changes: 7 additions & 0 deletions tests/fixtures/additional/ru/messages.ru.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?php

declare(strict_types=1);

return [
'should_be_override' => 'original'
];
3 changes: 2 additions & 1 deletion tests/fixtures/locales/ru/messages.ru.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@
declare(strict_types=1);

return [
'message' => 'translation'
'message' => 'translation',
'should_be_override' => 'changed by application translation'
];

0 comments on commit 1b9bef0

Please sign in to comment.