-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
L10N & I18N #1
Comments
$h= new Handlebars($path, (new I18n())
->dates('d.m.Y')
->times('H:i')
->separator(',')
->thousands('.')
->prices('%.2f EUR')
); |
Translations idea: (new Handlebars($path))->using(new Translations('texts.csv')); |
Language would need to be determined from the request:
In both scenarios, we could pass the determined language in request values and then react on that inside this template engine. Telling the template engine where to select the language from could be done by passing a |
This has been taken care of in #3 |
Example implementation of translations extension: <?php namespace org\example\skills;
use io\Path;
use io\streams\{TextReader, FileInputStream};
use text\csv\CsvMapReader;
use web\frontend\helpers\Extension;
class Translations extends Extension {
private $original;
private $texts= [];
/** Creates new translations from a CSV file */
public function __construct(string|Path $file) {
$reader= new CsvMapReader(new TextReader(new FileInputStream($file), 'utf-8'));
$translations= $reader->getHeaders();
$this->original= $translations[0];
foreach ($reader->withKeys($translations)->lines() as $record) {
$this->texts[$record[$this->original]]= $record;
}
}
/** Returns "t" helper */
public function helpers(): iterable {
yield 't' => function($in, $context, $options) {
$lang= $context->lookup('request', helpers: false)->value('user')['language'] ?? $this->original;
$text= array_shift($options);
return vsprintf($this->texts[$text][$lang] ?? $text, $options);
};
}
} {{t "Welcome %s!" self.name}}
{{t "Search users and skills..."}}
I chose to use CSV because there are enough GUIs to edit these files, even by not-too-technical folks. |
|
One idea would be to pass an individual context so that this could be rewritten to The other idea would be to have like a "scoped" engine, and then have: |
...which means the helper would be dependant on a certain engine implementation, which is OK as we control the engine and the helpers inside this library. Here's what we can do on the other hand: First, we need to construct templates with a function: $translation= new Translation(
$texts,
fn($context) => $context->lookup('request', helpers: false)->value('user')['language'] ?? null
); Second, we can cache the results of this function inside the context: yield 't' => function($in, $context, $options) {
$lang= $context->variables['lang'] ??= ($this->language)($context) ?? $this->original;
// ...
} |
The problem with the date and number helpers are that they do not take user preference into mind. Maybe this would work: // Always uses "d.m.Y" as date format
$engine= new Handlebars($templates, new Dates(formats: ['short' => 'd.m.Y']));
// Use locale from user object, would try [lang]_[region], [lang], then fall back to null
$engine= new Handlebars($templates, new ByLocale(
fn($context) => $context->lookup('request', helpers: false)->value('user')['locale'],
[
'en_US' => [new Numbers('.', ','), new Dates(formats: ['short' => 'm/d/Y'])],
'de' => [new Numbers(',', '.'), new Dates(formats: ['short' => 'd.m.Y'])],
null => [new Numbers(), new Dates(formats: ['short' => 'd.m.Y'])],
]
));
// Using the "intl" extension (https://www.php.net/manual/de/book.intl.php)
$engine= new Handlebars($templates, new ByLocale(
fn($context) => $context->lookup('request', helpers: false)->value('user')['locale'],
fn($locale) => [Numbers::using(new NumberFormatter($locale)), Dates::using(new IntlDateFormatter($locale))],
)); The locale could also be initially detected by looking at |
This opens possibilities to render contexts in different scopes, e.g. a HTTP request scope, which then pass language and internationalization preferences See xp-forge/handlebars-templates#1
See https://preview.npmjs.com/package/handlebars-i18n as a good example, though we might abstract the text file into a
Translations
interface and implementations for YAML, CSV etcetera.The text was updated successfully, but these errors were encountered: