diff --git a/README.md b/README.md index 5405dc3..1fb0491 100644 --- a/README.md +++ b/README.md @@ -210,3 +210,30 @@ fn ($string, $replace) => $replace($string, [ // So eloquent! ``` + +### Callable translation strings + +Gloss also adds support for callable translation strings. + +Those can be useful when you have some code for dealing with things like inflection. + +For example, consider these three language strings: +```php +'index' => ':resources', +'create' => 'Create :resource', +'edit' => 'Edit :resource :title', +'delete' => 'Delete :resource :title', +``` + +In many languages that have declension (inflection of nouns, read more about the complexities of localization on [in our documentation](https://lean-admin.dev/docs/localization)), the form of `:Resource` will be the same for `create`, `edit`, and `delete`. + +It would be painful to translate each string manually for no reason. A better solution is to use intelligent inflection logic **as the default, while still keeping the option to manually change specific strings if needed**. + +```php +'index' => fn ($resource) => nominative($resource, 'plural'), +'create' => fn ($resource) => 'Vytvořit ' . oblique($resource, 'singular'), +'edit' => fn ($resource, $title) => 'Upravit ' . oblique($resource, 'singular') . $title, +'delete' => fn ($resource, $title) => 'Smazat ' . oblique($resource, 'singular') . $title, +``` + +You could have logic like this (with your own helpers) for the default values, and only use the overrides when some words are have irregular grammar rules and need custom values. diff --git a/src/GlossTranslator.php b/src/GlossTranslator.php index 5549245..c6160f3 100644 --- a/src/GlossTranslator.php +++ b/src/GlossTranslator.php @@ -5,6 +5,7 @@ declare(strict_types=1); namespace Lean\Gloss; use Countable; +use Illuminate\Support\Arr; use Illuminate\Translation\Translator; class GlossTranslator extends Translator @@ -217,4 +218,23 @@ class GlossTranslator extends Translator $this->getSelector()->choose($line, $number, $locale), $replace ); } + + protected function getLine($namespace, $group, $locale, $item, array $replace) + { + $this->load($namespace, $group, $locale); + + $line = Arr::get($this->loaded[$namespace][$group][$locale], $item); + + if (is_string($line)) { + return $this->makeReplacements($line, $replace); + } else if (is_callable($line)) { + return app()->call($line, $replace); + } elseif (is_array($line) && count($line) > 0) { + foreach ($line as $key => $value) { + $line[$key] = $this->makeReplacements($value, $replace); + } + + return $line; + } + } } diff --git a/tests/GlossTest.php b/tests/GlossTest.php index faaf358..4f4795d 100644 --- a/tests/GlossTest.php +++ b/tests/GlossTest.php @@ -315,6 +315,18 @@ class GlossTest extends TestCase $this->assertSame('YYY', gloss('test.abc', ['resource' => 'y'])); } + /** @test */ + public function closures_can_be_used_in_translation_strings() + { + $this->addMessages('en', 'test', [ + 'foo' => fn () => 'bar', + 'abc' => fn ($resource, $title) => Str::upper($resource) . ' ' . Str::lower($title), + ]); + + $this->assertSame('bar', gloss('test.foo')); + $this->assertSame('PRODUCT macbook pro', gloss('test.abc', ['resource' => 'product', 'title' => 'MacBook Pro'])); + } + protected function addMessage(string $key, string $value, string $locale = 'en', string $group = 'test', string $namespace = null): void { $this->addMessages($locale, $group, [$key => $value], $namespace);