Skip to content

Commit

Permalink
allow fluent functions registration
Browse files Browse the repository at this point in the history
resolves #3
  • Loading branch information
jrmajor committed Feb 4, 2022
1 parent 0186b7f commit a5e6dd9
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 1 deletion.
25 changes: 24 additions & 1 deletion src/FluentTranslator.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,24 @@

namespace Major\Fluent\Laravel;

use Closure;
use Countable;
use Illuminate\Contracts\Translation\Loader;
use Illuminate\Contracts\Translation\Translator as TranslatorContract;
use Illuminate\Filesystem\Filesystem;
use Illuminate\Translation\MessageSelector;
use Illuminate\Translation\Translator as BaseTranslator;
use Major\Fluent\Bundle\FluentBundle;
use Major\Fluent\Exceptions\Bundle\FunctionExistsException;

final class FluentTranslator implements TranslatorContract
{
/** @var array<string, array<string, FluentBundle|false>> */
private array $loaded = [];

/** @var array<string, Closure> */
private array $functions = [];

public function __construct(
protected BaseTranslator $baseTranslator,
protected Filesystem $files,
Expand Down Expand Up @@ -62,6 +67,23 @@ public function get($key, array $replace = [], $locale = null, bool $fallback =
return $message ?? $this->baseTranslator->get(...func_get_args());
}

public function addFunction(string $name, Closure $function): void
{
if (array_key_exists($name, $this->functions)) {
throw new FunctionExistsException($name);
}

$this->functions[$name] = $function;

foreach ($this->loaded as $locale) {
foreach ($locale as $bundle) {
if ($bundle !== false) {
$bundle->addFunction($name, $function);
}
}
}
}

private function getBundle(string $locale, string $group): ?FluentBundle
{
if (! isset($this->loaded[$locale][$group])) {
Expand All @@ -80,7 +102,8 @@ private function loadFtl(string $locale, string $group): ?FluentBundle
}

return (new FluentBundle($locale, ...$this->bundleOptions))
->addFtl($this->files->get($path));
->addFtl($this->files->get($path))
->addFunctions($this->functions);
}

/**
Expand Down
59 changes: 59 additions & 0 deletions tests/FunctionsTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
<?php

namespace Major\Fluent\Laravel\Tests;

use Major\Fluent\Exceptions\Bundle\FunctionExistsException;
use Major\Fluent\Exceptions\Resolver\ReferenceException;

final class FunctionsTest extends TestCase
{
/**
* @testdox function can be used
*/
public function testUsage(): void
{
$this->translator->addFunction('CONCAT', fn (string ...$args) => implode($args));

$this->assertSame('FooBar', __('functions.strings'));
}

/**
* @testdox arguments can be passed to function
*/
public function testArguments(): void
{
$this->translator->addFunction('CONCAT', fn (string ...$args) => implode($args));

$this->assertSame('BarBaz', __('functions.args', ['foo' => 'Bar', 'bar' => 'Baz']));
}

/**
* @testdox function can not be registered twice
*/
public function testRegisterTwice(): void
{
$this->expectException(FunctionExistsException::class);
$this->expectExceptionMessage('Attempt to override an existing function: CONCAT().');

$this->translator->addFunction('CONCAT', fn (string ...$args) => implode($args));
$this->translator->addFunction('CONCAT', fn (string ...$args) => implode(', ', $args));
}

/**
* @testdox function can be registered after bundle is resolved
*/
public function testLateRegistration(): void
{
try {
$this->assertSame('FooBar', __('functions.strings'));

$this->fail('Exception should have been thrown.');
} catch (ReferenceException $e) {
$this->assertSame('Unknown function: CONCAT().', $e->getMessage());
}

$this->translator->addFunction('CONCAT', fn (string ...$args) => implode($args));

$this->assertSame('FooBar', __('functions.strings'));
}
}
2 changes: 2 additions & 0 deletions tests/lang/pl/functions.ftl
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
strings = { CONCAT("Foo", "Bar") }
args = { CONCAT($foo, $bar) }

0 comments on commit a5e6dd9

Please sign in to comment.