Skip to content

Fluent localization system for PHP

License

Notifications You must be signed in to change notification settings

jrmajor/fluent-php

Repository files navigation

jrmajor/fluent

Latest Stable Version Required PHP Version

A PHP implementation of the Project Fluent, a localization system designed by Mozilla to unleash the expressive power of the natural language.

Read the Fluent Syntax Guide or try it out in the Fluent Playground to learn more about the syntax.

shared-photos =
    { $userName } { $photoCount ->
        [one] added a new photo
       *[other] added { $photoCount } new photos
    } to { $userGender ->
        [male] his stream
        [female] her stream
       *[other] their stream
    }.
$bundle->message('stream.shared-photos', [
    'userName' => 'jrmajor',
    'photoCount' => 2,
    'userGender' => 'male',
]); // jrmajor added 2 new photos to his stream.

You may install this package via Composer: composer require jrmajor/fluent.

Use jrmajor/laravel-fluent to integrate Fluent translations into your Laravel application.

Usage

Parsing

use Major\Fluent\Parser\FluentParser;

$parser = new FluentParser(strict: true);

$resource = $parser->parse('hello-user = Hello, { $userName }!');

$strict constructor argument defaults to false. In strict mode syntax errors result in a ParserException. Otherwise, they are ignored and represented in AST by Junk.

Message formatting

use Major\Fluent\Bundle\FluentBundle;

$bundle = new FluentBundle('en', strict: true);

$bundle->addResource($resource);
// or
$bundle->addFtl('hello-user = Hello, { $userName }!');

$bundle->message('hello-user', userName: 'World'); // Hello, World!

FluentBundle is single-language store of translation resources. Its constructor accepts following arguments:

  • string $locale: Locale to instantiate locale-specific formatters (e.g. en-US, pl, zh-Hant-TW, fr-CA).
  • bool $strict = false: See handling errors.
  • bool $useIsolating = true: Specifying whether to use Unicode isolation marks (FSI, PDI) for bidirectional interpolations.
  • bool $allowOverrides = false: Allow overriding existing messages and terms.

Adding resources

Translations can be added to bundle using addResource() or addFtl() methods. The first one accepts FluentResource object returned by the parser, while the second one accepts a raw FTL string.

addResource(FluentResource $resource, bool $allowOverrides = null): static

addFtl(string $ftl, bool $allowOverrides = null): static

If $allowOverrides is null, bundle default will be used.

If bundle is in strict mode, $ftl parsing will be also done in strict mode.

Formatting messages

message(string $_message, mixed ...$arguments): ?string

message() method accepts an id of a message as a first parameter and message arguments as named parameters. It returns null for missing messages.

welcome = Welcome
    .guest = Welcome, Guest
    .user = Welcome, { $userName }
$bundle->message('welcome'); // Welcome

$bundle->message('goodbye'); // null

For attributes, you may use “dot” notation:

$bundle->message('welcome.guest'); // Welcome, Guest

Message arguments may be passed as named arguments or as an associative array:

$bundle->message('welcome.user', userName: 'John'); // Welcome, John
// equivalent to
$bundle->message('welcome.user', ['userName' => 'John']); // Welcome, John

Handling errors

By default, all resolver exceptions are ignored and can be obtained using popErrors() method. It returns an array of exceptions and clears exception cache, which means the next time you call it, it will return only new errors.

$bundle->message('welcome.user'); // Welcome, {$userName}

$errors = $bundle->popErrors();

count($errors);           // 1
$errors[0]->getMessage(); // Unknown variable: $userName.

All resolver exceptions extend ResolverException. In strict mode they would be thrown right away in message() call.

Testing

vendor/bin/phpunit           # Tests
vendor/bin/phpstan analyze   # Static analysis
vendor/bin/php-cs-fixer fix  # Formatting