mirror of
https://github.com/rlanvin/php-rrule.git
synced 2024-12-01 08:24:10 +01:00
Add custom_path option to humanReadable
If the option is present, it'll first look for a file in this folder before looking into the default folder. Fix #56
This commit is contained in:
parent
7c93c0e48a
commit
200b923c9e
@ -4,6 +4,10 @@
|
||||
|
||||
- Rewrite the core algorithm to use a native PHP generator, drop compability with PHP < 5.6 [#43](https://github.com/rlanvin/php-rrule/issues/43)
|
||||
|
||||
### Added
|
||||
|
||||
- New option `custom_path` to `humanReadable()` to use custom translation files [#56](https://github.com/rlanvin/php-rrule/issues/56)
|
||||
|
||||
## [1.6.3] - 2019-01-13
|
||||
|
||||
### Fixed
|
||||
|
@ -2153,7 +2153,7 @@ class RRule implements RRuleInterface
|
||||
* Test if intl extension is loaded
|
||||
* @return bool
|
||||
*/
|
||||
static public function intlLoaded()
|
||||
static protected function intlLoaded()
|
||||
{
|
||||
if ( self::$intl_loaded === null ) {
|
||||
self::$intl_loaded = extension_loaded('intl');
|
||||
@ -2163,10 +2163,11 @@ class RRule implements RRuleInterface
|
||||
|
||||
/**
|
||||
* Parse a locale and returns a list of files to load.
|
||||
* For example "fr_FR" will produce "fr" and "fr_FR"
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
static public function i18nFilesToLoad($locale, $use_intl = null)
|
||||
static protected function i18nFilesToLoad($locale, $use_intl = null)
|
||||
{
|
||||
if ( $use_intl === null ) {
|
||||
$use_intl = self::intlLoaded();
|
||||
@ -2202,26 +2203,38 @@ class RRule implements RRuleInterface
|
||||
*
|
||||
* @param string $locale
|
||||
* @param string|null $fallback
|
||||
* @param bool $use_intl
|
||||
* @param string $custom_path
|
||||
*
|
||||
* @return array
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
static protected function i18nLoad($locale, $fallback = null, $use_intl = null)
|
||||
static protected function i18nLoad($locale, $fallback = null, $use_intl = null, $custom_path = null)
|
||||
{
|
||||
$files = self::i18nFilesToLoad($locale, $use_intl);
|
||||
|
||||
$base_path = __DIR__.'/i18n';
|
||||
|
||||
$result = array();
|
||||
foreach ( $files as $file ) {
|
||||
$path = __DIR__."/i18n/$file.php";
|
||||
if ( isset(self::$i18n[$file]) ) {
|
||||
$result = array_merge($result, self::$i18n[$file]);
|
||||
}
|
||||
elseif ( is_file($path) && is_readable($path) ) {
|
||||
self::$i18n[$file] = include $path;
|
||||
$result = array_merge($result, self::$i18n[$file]);
|
||||
|
||||
// if the file exists in $custom_path, it overrides the default
|
||||
if ( $custom_path && is_file("$custom_path/$file.php") ) {
|
||||
$path = "$custom_path/$file.php";
|
||||
}
|
||||
else {
|
||||
self::$i18n[$file] = array();
|
||||
$path = "$base_path/$file.php";
|
||||
}
|
||||
|
||||
if ( isset(self::$i18n[$path]) ) {
|
||||
$result = array_merge($result, self::$i18n[$path]);
|
||||
}
|
||||
elseif ( is_file($path) && is_readable($path) ) {
|
||||
self::$i18n[$path] = include $path;
|
||||
$result = array_merge($result, self::$i18n[$path]);
|
||||
}
|
||||
else {
|
||||
self::$i18n[$path] = array();
|
||||
}
|
||||
}
|
||||
|
||||
@ -2237,7 +2250,7 @@ class RRule implements RRuleInterface
|
||||
|
||||
/**
|
||||
* Format a rule in a human readable string
|
||||
* intl extension is required.
|
||||
* `intl` extension is required.
|
||||
*
|
||||
* Available options
|
||||
*
|
||||
@ -2249,6 +2262,9 @@ class RRule implements RRuleInterface
|
||||
* | `date_formatter` | callable| Function used to format the date (takes date, returns formatted)
|
||||
* | `explicit_inifite`| bool | Mention "forever" if the rule is infinite (true)
|
||||
* | `dtstart` | bool | Mention the start date (true)
|
||||
* | `include_start` | bool |
|
||||
* | `include_until` | bool |
|
||||
* | `custom_path` | string |
|
||||
*
|
||||
* @param array $opt
|
||||
*
|
||||
@ -2267,7 +2283,8 @@ class RRule implements RRuleInterface
|
||||
'fallback' => 'en',
|
||||
'explicit_infinite' => true,
|
||||
'include_start' => true,
|
||||
'include_until' => true
|
||||
'include_until' => true,
|
||||
'custom_path' => null
|
||||
);
|
||||
|
||||
// attempt to detect default locale
|
||||
@ -2295,7 +2312,7 @@ class RRule implements RRuleInterface
|
||||
|
||||
$opt = array_merge($default_opt, $opt);
|
||||
|
||||
$i18n = self::i18nLoad($opt['locale'], $opt['fallback'], $opt['use_intl']);
|
||||
$i18n = self::i18nLoad($opt['locale'], $opt['fallback'], $opt['use_intl'], $opt['custom_path']);
|
||||
|
||||
if ( $opt['date_formatter'] && ! is_callable($opt['date_formatter']) ) {
|
||||
throw new \InvalidArgumentException('The option date_formatter must callable');
|
||||
|
@ -2629,15 +2629,19 @@ class RRuleTest extends TestCase
|
||||
*/
|
||||
public function testI18nFilesToLoadWithIntl($locale, $files)
|
||||
{
|
||||
$reflector = new ReflectionClass('RRule\RRule');
|
||||
$method = $reflector->getMethod('i18nFilesToLoad');
|
||||
$method->setAccessible(true);
|
||||
|
||||
if ( ! $files ) {
|
||||
try {
|
||||
$files = RRule::i18nFilesToLoad($locale, true);
|
||||
$method->invokeArgs(null, array($locale, true));
|
||||
$this->fail('Expected InvalidArgumentException not thrown (files was '.json_encode($files).')');
|
||||
} catch (\InvalidArgumentException $e) {
|
||||
}
|
||||
}
|
||||
else {
|
||||
$this->assertEquals($files, RRule::i18nFilesToLoad($locale, true));
|
||||
$this->assertEquals($files,$method->invokeArgs(null, array($locale, true)));
|
||||
}
|
||||
}
|
||||
|
||||
@ -2646,15 +2650,19 @@ class RRuleTest extends TestCase
|
||||
*/
|
||||
public function testI18nFilesToLoadWithoutIntl($locale, $dummy, $files)
|
||||
{
|
||||
$reflector = new ReflectionClass('RRule\RRule');
|
||||
$method = $reflector->getMethod('i18nFilesToLoad');
|
||||
$method->setAccessible(true);
|
||||
|
||||
if ( ! $files ) {
|
||||
try {
|
||||
RRule::i18nFilesToLoad($locale, false);
|
||||
$method->invokeArgs(null, array($locale, false));
|
||||
$this->fail('Expected InvalidArgumentException not thrown (files was '.json_encode($files).')');
|
||||
} catch (\InvalidArgumentException $e) {
|
||||
}
|
||||
}
|
||||
else {
|
||||
$this->assertEquals($files, RRule::i18nFilesToLoad($locale, false));
|
||||
$this->assertEquals($files, $method->invokeArgs(null, array($locale, false)));
|
||||
}
|
||||
}
|
||||
|
||||
@ -2755,8 +2763,6 @@ class RRuleTest extends TestCase
|
||||
'dtstart' => '2007-01-01'
|
||||
));
|
||||
|
||||
$reflector = new ReflectionClass('RRule\RRule');
|
||||
|
||||
setlocale(LC_MESSAGES, 'C');
|
||||
$this->assertNotEmpty($rrule->humanReadable(array('fallback' => null)), 'C locale is converted to "en"');
|
||||
}
|
||||
@ -2805,6 +2811,22 @@ class RRuleTest extends TestCase
|
||||
array('locale' => "en_IE", 'include_start' => false, 'explicit_infinite' => false),
|
||||
"daily"
|
||||
),
|
||||
// with custom_path
|
||||
'custom_path' => array(
|
||||
"DTSTART:20170202T000000Z\nRRULE:FREQ=YEARLY;UNTIL=20170205T000000Z",
|
||||
array('locale' => "fr_BE", "custom_path" => __DIR__."/i18n"),
|
||||
"chaque année, à partir du 2/02/17, jusqu'au 5/02/17"
|
||||
),
|
||||
'custom_path cached separately' => array(
|
||||
"DTSTART:20170202T000000Z\nRRULE:FREQ=YEARLY;UNTIL=20170205T000000Z",
|
||||
array('locale' => "fr_BE"),
|
||||
"tous les ans, à partir du 2/02/17, jusqu'au 5/02/17",
|
||||
),
|
||||
array(
|
||||
"RRULE:FREQ=DAILY;UNTIL=20190405T055959Z",
|
||||
array('locale' => "xx", "custom_path" => __DIR__."/i18n", "date_formatter" => function($date) { return "X"; }),
|
||||
"daily, starting from X, until X"
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
9
tests/i18n/fr_BE.php
Executable file
9
tests/i18n/fr_BE.php
Executable file
@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
return array(
|
||||
'yearly' => array(
|
||||
'1' => 'chaque année',
|
||||
'2' => 'une années sur deux',
|
||||
'else' => 'toutes les %{interval} années'
|
||||
)
|
||||
);
|
153
tests/i18n/xx.php
Executable file
153
tests/i18n/xx.php
Executable file
@ -0,0 +1,153 @@
|
||||
<?php
|
||||
|
||||
return array(
|
||||
'yearly' => array(
|
||||
'1' => 'yearly',
|
||||
'else' => 'every %{interval} years'
|
||||
),
|
||||
'monthly' => array(
|
||||
'1' => 'monthly',
|
||||
'else' => 'every %{interval} months'
|
||||
),
|
||||
'weekly' => array(
|
||||
'1' => 'weekly',
|
||||
'2' => 'every other week',
|
||||
'else' => 'every %{interval} weeks'
|
||||
),
|
||||
'daily' => array(
|
||||
'1' => 'daily',
|
||||
'2' => 'every other day',
|
||||
'else' => 'every %{interval} days'
|
||||
),
|
||||
'hourly' => array(
|
||||
'1' => 'hourly',
|
||||
'else' => 'every %{interval} hours'
|
||||
),
|
||||
'minutely' => array(
|
||||
'1' => 'minutely',
|
||||
'else' => 'every %{interval} minutes'
|
||||
),
|
||||
'secondly' => array(
|
||||
'1' => 'secondly',
|
||||
'else' => 'every %{interval} seconds'
|
||||
),
|
||||
'dtstart' => ', starting from %{date}',
|
||||
'infinite' => ', forever',
|
||||
'until' => ', until %{date}',
|
||||
'count' => array(
|
||||
'1' => ', one time',
|
||||
'else' => ', %{count} times'
|
||||
),
|
||||
'and' => 'and',
|
||||
'x_of_the_y' => array(
|
||||
'yearly' => '%{x} of the year', // e.g. the first Monday of the year, or the first day of the year
|
||||
'monthly' => '%{x} of the month',
|
||||
),
|
||||
'bymonth' => ' in %{months}',
|
||||
'months' => array(
|
||||
1 => 'January',
|
||||
2 => 'February',
|
||||
3 => 'March',
|
||||
4 => 'April',
|
||||
5 => 'May',
|
||||
6 => 'June',
|
||||
7 => 'July',
|
||||
8 => 'August',
|
||||
9 => 'September',
|
||||
10 => 'October',
|
||||
11 => 'November',
|
||||
12 => 'December',
|
||||
),
|
||||
'byweekday' => ' on %{weekdays}',
|
||||
'weekdays' => array(
|
||||
1 => 'Monday',
|
||||
2 => 'Tuesday',
|
||||
3 => 'Wednesday',
|
||||
4 => 'Thursday',
|
||||
5 => 'Friday',
|
||||
6 => 'Saturday',
|
||||
7 => 'Sunday',
|
||||
),
|
||||
'nth_weekday' => array(
|
||||
'1' => 'the first %{weekday}', // e.g. the first Monday
|
||||
'2' => 'the second %{weekday}',
|
||||
'3' => 'the third %{weekday}',
|
||||
'else' => 'the %{n}th %{weekday}'
|
||||
),
|
||||
'-nth_weekday' => array(
|
||||
'-1' => 'the last %{weekday}', // e.g. the last Monday
|
||||
'-2' => 'the penultimate %{weekday}',
|
||||
'-3' => 'the antepenultimate %{weekday}',
|
||||
'else' => 'the %{n}th to the last %{weekday}'
|
||||
),
|
||||
'byweekno' => array(
|
||||
'1' => ' on week %{weeks}',
|
||||
'else' => ' on weeks number %{weeks}'
|
||||
),
|
||||
'nth_weekno' => '%{n}',
|
||||
'bymonthday' => ' on %{monthdays}',
|
||||
'nth_monthday' => array(
|
||||
'1' => 'the 1st',
|
||||
'2' => 'the 2nd',
|
||||
'3' => 'the 3rd',
|
||||
'21' => 'the 21st',
|
||||
'22' => 'the 22nd',
|
||||
'23' => 'the 23rd',
|
||||
'31' => 'the 31st',
|
||||
'else' => 'the %{n}th'
|
||||
),
|
||||
'-nth_monthday' => array(
|
||||
'-1' => 'the last day',
|
||||
'-2' => 'the penultimate day',
|
||||
'-3' => 'the antepenultimate day',
|
||||
'-21' => 'the 21st to the last day',
|
||||
'-22' => 'the 22nd to the last day',
|
||||
'-23' => 'the 23rd to the last day',
|
||||
'-31' => 'the 31st to the last day',
|
||||
'else' => 'the %{n}th to the last day'
|
||||
),
|
||||
'byyearday' => array(
|
||||
'1' => ' on %{yeardays} day',
|
||||
'else' => ' on %{yeardays} days'
|
||||
),
|
||||
'nth_yearday' => array(
|
||||
'1' => 'the first',
|
||||
'2' => 'the second',
|
||||
'3' => 'the third',
|
||||
'else' => 'the %{n}th'
|
||||
),
|
||||
'-nth_yearday' => array(
|
||||
'-1' => 'the last',
|
||||
'-2' => 'the penultimate',
|
||||
'-3' => 'the antepenultimate',
|
||||
'else' => 'the %{n}th to the last'
|
||||
),
|
||||
'byhour' => array(
|
||||
'1' => ' at %{hours}',
|
||||
'else' => ' at %{hours}'
|
||||
),
|
||||
'nth_hour' => '%{n}h',
|
||||
'byminute' => array(
|
||||
'1' => ' at minute %{minutes}',
|
||||
'else' => ' at minutes %{minutes}'
|
||||
),
|
||||
'nth_minute' => '%{n}',
|
||||
'bysecond' => array(
|
||||
'1' => ' at second %{seconds}',
|
||||
'else' => ' at seconds %{seconds}'
|
||||
),
|
||||
'nth_second' => '%{n}',
|
||||
'bysetpos' => ', but only %{setpos} instance of this set',
|
||||
'nth_setpos' => array(
|
||||
'1' => 'the first',
|
||||
'2' => 'the second',
|
||||
'3' => 'the third',
|
||||
'else' => 'the %{n}th'
|
||||
),
|
||||
'-nth_setpos' => array(
|
||||
'-1' => 'the last',
|
||||
'-2' => 'the penultimate',
|
||||
'-3' => 'the antepenultimate',
|
||||
'else' => 'the %{n}th to the last'
|
||||
)
|
||||
);
|
Loading…
Reference in New Issue
Block a user