sroehrl / php-i18n-translate
Simple yet powerful i18n support for PHP projects
Requires
- ext-dom: *
- ext-mbstring: *
- neoan3-apps/template: ^2.0
Requires (Dev)
- phpunit/phpunit: 9.5.21
This package is auto-updated.
Last update: 2024-10-17 05:08:05 UTC
README
Straight forward. Convenient. Fast.
Installation
composer require sroehrl/php-i18n-translate
require_once 'vendor/autoload.php'; $i18n = new I18nTranslate\Translate(); $i18n->setTranslations('de', [ 'hello' => 'hallo', 'goose' => ['Gans', 'Gänse'] ]);
Quick start:
1. In Code
echo "a: " . $i18n->t('hello') . "<br>"; echo "b: " . $i18n->t('goose') . "<br>"; echo "c: " . $i18n->t('goose.plural') . "<br>"; // detect plural by numeric value foreach([0,1,2] as $number){ echo $number . " " . $i18n->t('goose', $number) . ", "; }
Outputs:
a: hallo <br> b: Gans <br> c: Gänse <br> 0 Gänse, 1 Gans, 2 Gänse
2. In HTML
main.html
<!-- We haven't provided any locale, so the ACCEPTED LANGUAGE header is used --> <p i18n-date>03/06/2009</p> <!-- If no value is present, the current timestamp is used --> <p i18n-date="\`y H:i"></p> <!-- If it's not a timestamp, things become smart --> <p i18n-date="d.m">next monday</p> <div> <p>Event starts @ <strong i18n-time>12:30</strong> (That's <span i18n-time-local="hh:mm a">12:30</span> your time)</p> </div> <!-- let's translate again, using the t-tag --> <p><t>goose</t></p> <p><t>goose.plural</t></p>
... echo $i18n->translate(file_get_contents('main.html'));
Outputs:
<!-- We haven't provided any locale, so the ACCEPTED LANGUAGE header is used --> <p>06.03.2009</p> <!-- In no value is present, the current timestamp is used --> <p>`22 13:14</p> <!-- If it's not a timestamp, things become smart --> <p>22.06</p> <div> <p>Event starts @ <strong>12:30 EDT</strong> (That's <span>9:30 am</span> your time)</p> </div> <!-- let's translate again, using the t-tag --> <p><t>Gans</t></p> <p><t>Gänse</t></p>
Table of Contents
- Installation
- Quick Start
- Table of Contents
- Initialization
- Setting up translations
- Time, Date, Currencies & Numbers
- Time & Date Formats
- Usage with "Template" recommended
- Placeholders & Dynamic values
Initialization
$t = new I18nTranslate(string $locale = null, string $clientTimezone = null)
You can initialize either with or without a ISO-locale (e.g. 'en-US'). If no value is provided, the class first tries to set the locale by the ACCEPT_LANGUAGE header and if that fails defaults to "en-US". If you don't pass a $clientTimeZone (e.g. 'Europe/Paris'), then a guess is made based on the locale. This can potentially lead to time offsets in countries with multiple timezones.
TIPS:
Timezones: There are several "timezone-guessing" mechanisms around. Using JavaScript is usually the most reliable way.
Settings: When dealing with internationalization, setting your server & database to UTC is a battle-tested approach.
Setting up translations
Whether you read your translations from a database or a file: gettext is not required, and you are expected to
run the method setTranslations
for every language you support.
$t = new I18nTranslate(); $all = [ ['eo' => ['blue' => 'blua',...]], ['jp' => ['blue' => '青い',...]], // BTW: make sure to consider encoding ['de' => ['blue' => 'blau',...]], ]; foreach($all as $lang => $translations){ $t->setTranslations($lang, $translations); }
$t->setDebug(true)
Will output a missing key message when a translation isn't set, rather than the following default behavior. This can be useful while developing/translating.
- If the language is not found, the class will default to the first defined language
- If a key is not found, the class will return the key
- If the key has a suffix (.plural), it will be removed
About locale-translations: The decision to ignore the country-specification on the locale on translations is intended. While formatting reacts to the differences of country localisation, translations do not. Example en-US vs. en-EN: the date formatting will react to these differences, but translations like 'color' <=> 'colour' are not supported.
Time, Date, Currencies & Numbers
This package includes a formatter for currencies, numbers and dates. If you want to use its functionality outside of an HTML template, you can initialize it yourself.
The following converters are at your disposal:
- date (accepts optional format)
- date-local (accepts optional format)
- time (accepts optional format)
- time-local (accepts optional format)
- currency (accepts optional, but recommended, ISO currency code like "USD")
- number
$locale = 'en-US'; $clientTimeZone = 'America/New_York'; // or null to let the class make an educated guess $formatter = new I18nTranslate\Formatter(string $locale, $clientTimeZone); $convertToClientTime = $formatter->format('time-local'); $serverTime = time(); $clientTime = $convertToClientTime($serverTime); // e.g. 09:30 AM EDT $clientTime = $convertToClientTime($serverTime, 'h:mm'); // e.g. 9:30
In most scenarios the templating attributes will be sufficient to handle your needs:
<section i18n-number>12.34</section> <!-- with currencies we recommend setting a currency as it otherwise defaults to the user's locale... --> <section i18n-currency="CAD">12.34</section> <!-- ... But the following attributes accept formatting, but don't need it --> <section i18n-date="EEEE">tomorrow</section> <section i18n-date-local>tomorrow</section> <section i18n-time>9:30</section> <section i18n-time-local>9:30</section>
For a better understanding of how to pass values to your HTML, read here
Time & Date formats
This package uses the Intl-extension for PHP but has a fallback mechanisms. If you do not have Intl installed, localized transformation does not work.
Date & Time inputs are interpreted either as UNIX timestamps or strings supported by PHP's strtotime function.
Date & Time formats accepts strings in the format of ISO8601 date format So not PHP's date notation
I kindly ask contributors to find an appropriate list. Until then, this dated Zend list is the best I could find: formats
Default fallback formats:
Numbers and currencies work with or without the Intl-extension, but might not conform to the ISO 8601 standard without the Intl-extension.
The examples at Quick Start should help.
Using i18nTranslate with version 2+ of the neoan3-apps/template engine.
Under the hood this package interprets html-files with the help of neoan3-apps/template. It is therefore already available to you once you installed this package. The following setup allows the template engine to run PRIOR to translations, making dynamic formats and values possible:
use I18nTranslate\Translate; use Neoan3\Apps\Template\Constants; use Neoan3\Apps\Template\Template; ... // your template path Constants::setPath(__DIR__ . '/view'); // initialize i18n $t = new Translate('de-DE); $t->setTranslations('de', [ 'woman' => ['Frau', 'Frauen'], 'man' => ['Mann', 'Männer'] ]); $regularRenderData = [ 'tomorrow' => time() + 60*60*24, 'format' => 'dd-MM-Y', 'iterateMe' => [0,1,2], 'fromCode' => $t->('man') ]; echo $t->translate(Template::embraceFromFile('/test.html', $regularRenderData));
test.html
<h2>{{fromCode}}</h2> <p>Hackathon @ <span i18n-date>{{tomorrow}}</span></p> <p i18n-date="{{format}}">next monday</p> <div> <p n-for="iterateMe as number">{{number}} {{t(woman, {{number}})}}</p> </div>
Example-output:
<h2>Mann</h2> <p>Hackathon @ <span>20.08.2022</span></p> <p>22-08-22</p> <div> <p>0 Frauen</p> <p>1 Frau</p> <p>2 Frauen</p> </div>
Placeholders & Dynamic values
Placeholders are written embraced by [%
ans %]
(e.g. [% my-var %]
). They enable dynamic values within a translation.
... $t->setTranslations('de',[ 'Today I want to talk about [%subject%]' => 'Heute möchte ich über [%subject%] sprechen' ]) $context = [ 'personOfInterest' => 'Mr. T' ] echo $t->translate(Template::embraceFromFile('/belowHtml.html', $context));
<t>Today I want to talk about [%subject%](% Tom Brady %)</t>
... or when using template values:
<t>Today I want to talk about [%subject%](% {{personOfInterest}} %)</t>
Attributes as functions
When using the attributes within t-tags as functions, they can be referenced as follows:
- i18n-currency -> [%currency-value%]
- i18n-time, i18n-time-local -> [%time-value%]
- i18n-date, i18n-date-local -> [%date-value%]
- i18n-number -> [%number-value%]