一个使用Unicode CLDR进行应用程序本地化的API

v4.1.3 2024-02-22 18:17 UTC

README

Packagist Code Quality Code Coverage Downloads

CLDR 包通过利用Unicode通用区域数据存储库(CLDR)定义的数据和约定,为您的应用程序提供国际化支持。它提供了许多有用的区域信息和数据(如地区名称、语言、日期等),以及数字、货币、日期和时间、单位、序列、列表等的格式化程序。

注意

该包针对CLDR版本36

示例用法

<?php

/* @var ICanBoogie\CLDR\Repository $repository */

# You get a locale from the repository, here the locale for French.
$fr = $repository->locales['fr'];

# You can use a locale instance as an array to get data
echo $fr['characters']['auxiliary'];                // [á å ä ã ā ē í ì ī ñ ó ò ö ø ú ǔ]
echo $fr['delimiters']['quotationStart'];           // «
echo $fr['territories']['TF'];                      // Terres australes françaises

# You can localize it, to get its local name for example
echo $fr->localize($fr)->name;                      // Français

# You can format numbers, percents, currencies, and lists directly from there
echo $fr->format_number(12345.67);                  // 12 345,67
echo $fr->format_percent(.1234567);                 // 12 %
echo $fr->format_currency(12345.67, 'EUR');         // 12 345,67 €
echo $fr->format_list([ "Un", "deux", "trois" ]);   // Un, deux et trois

# You can get the default calendar for that locale, and access its data
$calendar = $fr->calendar;
echo $calendar['days']['format']['wide']['sun'];    // dimanche
echo $calendar->wide_days['sun'];                   // dimanche

# You can use the calendar to format dates and times, or both
$datetime = '2018-11-24 20:12:22 UTC';
echo $calendar->format_date($datetime, 'long');     // 24 novembre 2018
echo $calendar->format_time($datetime, 'long');     // 20:12:22 UTC
echo $calendar->format_datetime($datetime, 'full'); // samedi 24 novembre 2018 à 20:12:22 UTC

# Alternatively, you can localize a DateTimeInterface instance and get formatted dates of various length
$datetime = new \DateTime('2013-11-04 20:21:22 UTC');
$fr_datetime = $fr->localize($datetime);
echo $fr_datetime->as_full;                         // lundi 4 novembre 2013 à 20:21:22 UTC
echo $fr_datetime->as_long;                         // 4 novembre 2013 à 20:21:22 UTC
echo $fr_datetime->as_medium;                       // 4 nov. 2013 20:21:22
echo $fr_datetime->as_short;                        // 04/11/2013 20:21

# You can format units
$units = $repository->locales['en']->units;
echo $units->duration_hour->name;                   // hours
echo $units->duration_hour->short_name;             // h
echo $units->duration_hour(1);                      // 1 hour
echo $units->duration_hour(23);                     // 23 hours
echo $units->duration_hour(23)->as_short;           // 23 hr
echo $units->duration_hour(23)->as_narrow;          // 23h

# You can format a unit per another unit
echo $units->volume_liter(12.345)->per($units->duration_hour);
// 12.345 liters per hour
echo $units->volume_liter(12.345)->per($units->duration_hour)->as_short;
// 12.345 L/h
echo $units->volume_liter(12.345)->per($units->duration_hour)->as_narrow;
// 12.345L/h

# You can format sequences of units
$units->sequence->angle_degree(5)->duration_minute(30)->as_narrow;
// 5° 30m
$units->sequence->length_foot(3)->length_inch(2)->as_short;
// 3 ft, 2 in

# You can access plural rules
$repository->plurals->rule_for(1.5, 'fr'); // one
$repository->plurals->rule_for(2, 'fr');   // other
$repository->plurals->rule_for(2, 'ar');   // two

# You can access currencies and their localized data
$euro = $repository->currencies['EUR'];
$fr_euro = $euro->localize('fr');
echo $fr_euro->name;
echo $fr_euro->name_for(1);                         // euro
echo $fr_euro->name_for(10);                        // euros
echo $fr_euro->format(12345.67);                    // 12 345,67 €

# You can access territories and their localized data
$territory = $repository->territories['FR'];
echo $territory;                                    // FR
echo $territory->currency;                          // EUR
echo $territory->currency_at('1977-06-06');         // FRF
echo $territory->currency_at('now');                // EUR
echo $territory->name_as('fr-FR');                  // France
echo $territory->name_as('it');                     // Francia
echo $territory->name_as('ja');                     // フランス
echo $repository->territories['FR']->first_day;     // mon
echo $repository->territories['EG']->first_day;     // sat
echo $repository->territories['BS']->first_day;     // sun
echo $repository->territories['AE']->weekend_start; // fri
echo $repository->territories['AE']->weekend_end;   // sat
echo $territory->localize('fr')->name;              // France
echo $territory->localize('it')->name;              // Francia
echo $territory->localize('ja')->name;              // フランス

安装

composer require icanboogie/cldr

仓库

CLDR由一个仓库实例表示,数据由此访问。当需要时,数据通过提供者检索。web提供者从GitHub上托管的JSON分布获取数据。为了避免每次请求都击中网络,使用了一系列缓存,每个缓存都有自己的策略。

以下示例演示了如何实例化仓库

<?php

namespace ICanBoogie\CLDR;

use ICanBoogie\CLDR\Cache\CacheCollection;
use ICanBoogie\CLDR\Cache\FileCache;
use ICanBoogie\CLDR\Cache\RedisCache;
use ICanBoogie\CLDR\Cache\RuntimeCache;
use ICanBoogie\CLDR\Provider\CachedProvider;
use ICanBoogie\CLDR\Provider\WebProvider;

/* @var \Redis $redis_client */

$provider = new CachedProvider(
	new WebProvider,
	new CacheCollection([
		new RunTimeCache,
		new RedisCache($redis_client),
		new FileCache("/path/to/storage")
	])
);

$repository = new Repository($provider);

访问仓库

仓库可以像一个大数组一样访问,但它还提供了对最重要数据(如区域设置、地区、数字、货币等)的接口。

以下示例演示了如何使用仓库访问区域设置和补充数据

<?php

/* @var $repository \ICanBoogie\CLDR\Repository */

$english_locale = $repository->locales['en'];
$french_locale = $repository->locales['fr'];

$repository->available_locales;            // [ … 'en', …, 'fr', … ];
$repository->is_locale_available('fr');    // true
$repository->is_locale_available('fr-FR'); // false

$supplemental = $repository->supplemental;
# reading the default calendar
echo $supplemental['calendarPreferenceData']['001']; // gregorian

区域设置

区域设置的数据和约定由一个Locale实例表示,该实例可以用作数组来访问各种原始数据,如日历、字符、货币、分隔符、语言、地区等。

<?php

/* @var $repository \ICanBoogie\CLDR\Repository */

$locale = $repository->locales['fr'];

echo $locale['characters']['auxiliary'];      // [á å ä ã ā ē í ì ī ñ ó ò ö ø ú ǔ]
echo $locale['delimiters']['quotationStart']; // «
echo $locale['territories']['TF'];            // Terres australes françaises

区域设置提供一组日历,通常使用calendar属性来获取区域设置的默认日历。

<?php

/* @var $repository \ICanBoogie\CLDR\Repository */

$locale = $repository->locales['fr'];

echo $locale['ca-gregorian']['days']['format']['wide']['sun'];         // dimanche
# or using the calendar collection
echo $locale->calendars['gregorian']['days']['format']['wide']['sun']; // dimanche
# or because 'gregorian' is the default calendar for this locale
echo $locale->calendar['days']['format']['wide']['sun'];               // dimanche

本地化对象

区域设置也常用于本地化实例,如货币地区,甚至Locale。使用localize方法进行实例本地化。该方法会尽力找到一个合适的本地化器,如果实例实现了Localizable,或者定义了ICanBoogie\CLDR\Localized<class_base_name>类,则会有所帮助。

<?php

/* @var $repository \ICanBoogie\CLDR\Repository */

$datetime = new \DateTime;
$localized_datetime = $repository->locales['fr']->localize($datetime);
echo get_class($localized_datetime); // ICanBoogie\CLDR\LocalizedDateTime

可本地化的实例通常实现localize()方法。

<?php

/* @var $repository \ICanBoogie\CLDR\Repository */

echo $repository->territories['FR']->localize('fr')->name; // France

本地化区域设置

可以使用localize()方法或所需区域设置的localize()方法获取本地化区域设置。

<?php

/* @var $repository \ICanBoogie\CLDR\Repository */

$locale = $repository->locales['fr'];

echo $locale->localize('fr')->name;                         // Français
# or
echo $repository->locales['fr']->localize($locale)->name;   // Français

上下文转换

可以区分几个大写上下文,不同的语言对日期、日期元素、语言/地区/货币名称的大写行为有不同的约定。context_transform()方法有助于大写这些元素。

<?php

use ICanBoogie\CLDR\ContextTransforms;

/* @var $repository \ICanBoogie\CLDR\Repository */

echo $repository->locales['fr']->context_transform(
	"juin",
	ContextTransforms::USAGE_MONTH_FORMAT_EXCEPT_NARROW,
	ContextTransforms::TYPE_STAND_ALONE
);

// Juin

日历

日历由一个Calendar实例表示,它们可以作为数组访问,并提供了快速访问日、时代、月份和季度的魔术属性。

<?php

use ICanBoogie\CLDR\Calendar;

/* @var $repository \ICanBoogie\CLDR\Repository */

$calendar = new Calendar($repository->locales['fr'], $repository->locales['fr']['ca-gregorian']);
# or
$calendar = $repository->locales['fr']->calendars['gregorian'];
# or
$calendar = $repository->locales['fr']->calendar; // because "gregorian" is the default calendar for this locale

$calendar->standalone_abbreviated_days;
# or $calender['days']['stand-alone']['abbreviated'];

$calendar->abbreviated_days;
# or $calender['days']['format']['abbreviated'];

这可以与日、时代、月份、季度以及以下宽度一起使用: 缩写。以下是一些示例

<?php

/* @var $calendar \ICanBoogie\CLDR\Calendar */

$calendar->standalone_abbreviated_eras;
$calendar->standalone_narrow_months;
$calendar->standalone_short_quarters;
$calendar->standalone_wide_days;
$calendar->abbreviated_days;
$calendar->narrow_months;
$calendar->short_days;
$calendar->wide_quarters;

日期和时间格式化器

从日历中可以获取日期和时间的格式化器。

以下示例演示了如何访问和使用日期和时间格式化器。

<?php

/* @var $repository \ICanBoogie\CLDR\Repository */

$datetime = '2018-11-24 20:12:22 UTC';
$calendar = $repository->locales['fr']->calendar;

echo $calendar['days']['format']['wide']['sun'];    // dimanche
echo $calendar->wide_days['sun'];                   // dimanche

echo $calendar->format_datetime($datetime, 'full'); // samedi 24 novembre 2018 20:12:22 UTC
echo $calendar->format_date($datetime, 'long');     // 24 novembre 2018
echo $calendar->format_time($datetime, 'long');     // 20:12:22 UTC
# or
echo $calendar->datetime_formatter->format($datetime, 'full'); // samedi 24 novembre 2018 20:12:22 UTC
echo $calendar->date_formatter->format($datetime, 'long');     // 24 novembre 2018
echo $calendar->time_formatter->format($datetime, 'long');     // 20:12:22 UTC

日期和时间

日历为日期和时间提供格式化器。可以使用宽度、骨架或模式进行格式化。日期时间可以指定为 Unix 时间戳、字符串或 DateTime 实例。

<?php

use ICanBoogie\CLDR\DateTimeFormatter;

/* @var $repository \ICanBoogie\CLDR\Repository */

$formatter = new DateTimeFormatter($repository->locales['en']->calendar);
# or
$formatter = $repository->locales['en']->calendar->datetime_formatter;

$datetime = '2013-11-02 22:23:45 UTC';

echo $formatter($datetime, "MMM d, y");                 // November 2, 2013
echo $formatter($datetime, "MMM d, y 'at' hh:mm:ss a"); // November 2, 2013 at 10:23:45 PM
echo $formatter($datetime, $formatter::WIDTH_FULL);     // Saturday, November 2, 2013 at 10:23:45 PM UTC
echo $formatter($datetime, $formatter::WIDTH_LONG);     // November 2, 2013 at 10:23:45 PM UTC
echo $formatter($datetime, $formatter::WIDTH_MEDIUM);   // Nov 2, 2013, 10:23:45 PM
echo $formatter($datetime, $formatter::WIDTH_SHORT);    // 11/2/13, 10:23 PM
echo $formatter($datetime, ':Ehm');                     // Sat 10:23 PM

日期格式化器

日历为日期提供格式化器。使用宽度或模式进行格式化。

<?php

use ICanBoogie\CLDR\DateFormatter;

/* @var $repository \ICanBoogie\CLDR\Repository */

$formatter = new DateFormatter($repository->locales['en']->calendar);
# or
$formatter = $repository->locales['en']->calendar->date_formatter;

$datetime = '2013-11-05 21:22:23';

echo $formatter($datetime, $formatter::WIDTH_FULL);   // Tuesday, November 5, 2013
echo $formatter($datetime, $formatter::WIDTH_LONG);   // November 5, 2013
echo $formatter($datetime, $formatter::WIDTH_MEDIUM); // Nov 5, 2013
echo $formatter($datetime, $formatter::WIDTH_SHORT);  // 11/5/13

时间格式化器

日历为时间提供格式化器。使用宽度或模式进行格式化。

<?php

use ICanBoogie\CLDR\TimeFormatter;

/* @var $repository \ICanBoogie\CLDR\Repository */

$formatter = new TimeFormatter($repository->locales['en']->calendar);
# or
$formatter = $repository->locales['en']->calendar->time_formatter;

$datetime = '2013-11-05 21:22:23 UTC';

echo $formatter($datetime, $formatter::WIDTH_FULL);   // 9:22:23 PM UTC
echo $formatter($datetime, $formatter::WIDTH_LONG);   // 9:22:23 PM UTC
echo $formatter($datetime, $formatter::WIDTH_MEDIUM); // 9:22:23 PM
echo $formatter($datetime, $formatter::WIDTH_SHORT);  // 9:22 PM

本地化日期时间

DateTime 可以通过将其包装在 LocalizedDateTime 实例中或使用所需区域的 localize 方法进行本地化。

<?php

use ICanBoogie\CLDR\LocalizedDateTime;

/* @var $repository \ICanBoogie\CLDR\Repository */

$ldt = new LocalizedDateTime(new \DateTime('2013-11-04 20:21:22 UTC'), $repository->locales['fr']);
# or
$ldt = $repository->locales['fr']->localize(new \DateTime('2013-11-04 20:21:22 UTC'));

echo $ldt->as_full;          // lundi 4 novembre 2013 à 20:21:22 UTC
# or
echo $ldt->format_as_full(); // lundi 4 novembre 2013 à 20:21:22 UTC

echo $ldt->as_long;          // 4 novembre 2013 à 20:21:22 UTC
echo $ldt->as_medium;        // 4 nov. 2013 20:21:22
echo $ldt->as_short;         // 04/11/2013 20:21

数字格式化

可以使用 NumberFormatter 格式化数字。

<?php

use ICanBoogie\CLDR\NumberFormatter;

$formatter = new NumberFormatter;
$formatter(4123.37, "#,#00.#0");
// 4,123.37
$formatter(.3789, "#0.#0 %");
// 37.89 %

注意:您还可以从存储库中获取数字格式化器或格式化数字。

<?php

/* @var $repository \ICanBoogie\CLDR\Repository */

$number_formatter = $repository->number_formatter;

echo $repository->format_number(4123.37, "#,#00.#0"); // 4,123.37

本地化数字格式化

可以通过 localize() 方法(如果实例使用存储库创建)或所需区域的 localize() 方法获取本地化数字格式化器。默认情况下,列表使用 标准 类型进行格式化,但您也可以提供自己的模式。

<?php

use ICanBoogie\CLDR\NumberFormatter;
use ICanBoogie\CLDR\LocalizedNumberFormatter;

/* @var $repository \ICanBoogie\CLDR\Repository */

$formatter = new NumberFormatter($repository);

$localized_formatter = $repository->locales['fr']->localize($formatter);
# or
$localized_formatter = new LocalizedNumberFormatter($formatter, $repository->locales['fr']);

$localized_formatter(123456.78);
// 123 456,78
$repository->locales['en']->localize($formatter)->format(123456.78);
// 123,456.78

注意:您还可以从区域中获取本地化数字格式化器或格式化数字。

<?php

/* @var $repository \ICanBoogie\CLDR\Repository */

$localized_number_formatter = $repository->locales['fr']->number_formatter;
echo $repository->locales['fr']->format_number(123456.78);

列表格式化

可以使用 ListFormatter 格式化可变长度的列表,例如 "星期一、星期二、星期五和星期六"。

<?php

namespace ICanBoogie\CLDR;

$list_patterns = Locale\ListPattern::from([

	'start' => "{0}, {1}",
	'middle' => "{0}, {1}",
	'end' => "{0}, and {1}",
	'2' =>  "{0} and {1}"

]);

$formatter = new ListFormatter;

$formatter([ "Monday" ], $list_patterns);
// Monday
$formatter([ "Monday", "Tuesday" ], $list_patterns);
// Monday and Tuesday
$formatter([ "Monday", "Tuesday", "Friday" ], $list_patterns);
// Monday, Tuesday, and Friday
$formatter([ "Monday", "Tuesday", "Friday", "Saturday" ], $list_patterns);
// Monday, Tuesday, Friday, and Saturday

注意:您还可以从存储库中获取列表格式化器或格式化列表。

<?php

namespace ICanBoogie\CLDR;

/* @var $repository Repository */

$list_patterns = Locale\ListPattern::from([

	'2' =>  "{0} and {1}",
	'start' => "{0}, {1}",
	'middle' => "{0}, {1}",
	'end' => "{0}, and {1}",

]);

$list_formatter = $repository->list_formatter;
echo $repository->format_list([ "Monday", "Tuesday", "Friday" ], $list_patterns);

本地化列表格式化

可以通过 localize() 方法(如果实例使用存储库创建)或所需区域的 localize() 方法获取本地化列表格式化器。默认情况下,列表使用 "标准" 类型进行格式化,但还有更多类型可供选择,您还可以提供自己的列表模式。

<?php

namespace ICanBoogie\CLDR;

/* @var $repository \ICanBoogie\CLDR\Repository */

$formatter = new ListFormatter($repository);

$localized_formatter = $repository->locales['fr']->localize($formatter);
# or
$localized_formatter = new LocalizedListFormatter($formatter, $repository->locales['fr']);

$localized_formatter([ "lundi", "mardi", "vendredi", "samedi" ]);
# or
$localized_formatter([ "lundi", "mardi", "vendredi", "samedi" ], 'standard');
# or
$localized_formatter([ "lundi", "mardi", "vendredi", "samedi" ], LocalizedListFormatter::TYPE_STANDARD);
// lundi, mardi, vendredi et samedi

注意:您还可以从区域中获取本地化列表格式化器或格式化列表。

<?php

namespace ICanBoogie\CLDR;

/* @var $repository Repository */

$localized_list_formatter = $repository->locales['fr']->list_formatter;
echo $repository->locales['fr']->format_list([ "Monday", "Tuesday", "Friday" ]);

单位

可以格式化单位数量,如年、月、日、小时、分钟和秒,例如,在英语中为 "1天" 或 "3天"。通过区域单位轻松使用此功能。

<?php

/* @var $repository \ICanBoogie\CLDR\Repository */

$units = $repository->locales['en']->units;
echo $units->duration_hour->name;                   // hours
echo $units->duration_hour->short_name;             // h
echo $units->duration_hour(1);                      // 1 hour
echo $units->duration_hour(23);                     // 23 hours
echo $units->duration_hour(23)->as_short;           // 23 hr
echo $units->duration_hour(23)->as_narrow;          // 23h

许多单位可用.

每个单位

可以创建单位组合,如 每小时英里每秒升。一些单位已经具有 '预计算' 形式,如 kilometer_per_hour;存在此类单位时,应优先使用。

<?php

/* @var $repository \ICanBoogie\CLDR\Repository */

$units = $repository->locales['en']->units;
echo $units->volume_liter(12.345)->per($units->duration_hour);              // 12.345 liters per hour
echo $units->volume_liter(12.345)->per($units->duration_hour)->as_short;    // 12.345 Lph
echo $units->volume_liter(12.345)->per($units->duration_hour)->as_narrow;   // 12.345l/h

单位组合序列

单位可以用于组合序列,如 5° 30m 表示 5 度 30 分钟,或 3 ft, 2 in。为此,可以使用适当的宽度将单位组合成一个序列。

<?php

/* @var $repository \ICanBoogie\CLDR\Repository */

$units = $repository->locales['en']->units;

$units->sequence
	->angle_degree(5)
	->duration_minute(30)
	->as_narrow;
	// 5° 30m

$units->sequence
	->length_foot(3)
	->length_inch(2)
	->as_short;
	// 3 ft, 2 in

$units = $repository->locales['fr']->units;

$units->sequence
	->duration_hour(12)
	->duration_minute(34)
	->duration_second(45)
	->as_long;
	// 12 heures, 34 minutes et 56 secondes

$units->sequence
	->duration_hour(12)
	->duration_minute(34)
	->duration_second(45)
	->as_short;
	// 12 h, 34 min et 56 s

$units->sequence
	->duration_hour(12)
	->duration_minute(34)
	->duration_second(45)
	->as_narrow;
	// 12h 34m 56s

复数

语言对于表示零、一、两、几个、许多或其他数字有不同的复数规则。ICanBoogie 的 CLDR 使得查找任何数值的复数规则变得容易。

<?php

/* @var $repository \ICanBoogie\CLDR\Repository */

$repository->plurals->rules_for('fr'); // [ 'one', 'other' ]
$repository->plurals->rules_for('ar'); // [ 'zero', 'one', 'two', 'few', 'many', 'other' ]

$repository->plurals->rule_for(1.5, 'fr'); // one
$repository->plurals->rule_for(2, 'fr');   // other
$repository->plurals->rule_for(2, 'ar');   // two

领土

领土信息由 Territory 实例表示,该实例汇总了实际上散布在 CLDR 中的信息。

<?php

/* @var $repository \ICanBoogie\CLDR\Repository */

$territory = $repository->territories['FR'];

echo $territory;                                    // FR
echo $territory->currency;                          // EUR
echo $territory->currency_at('1977-06-06');         // FRF
echo $territory->currency_at('now');                // EUR

echo $territory->language;                          // fr
echo $territory->population;                        // 66259000

echo $territory->name_as('fr-FR');                  // France
echo $territory->name_as('it');                     // Francia
echo $territory->name_as('ja');                     // フランス

echo $territory->name_as_fr_FR;                     // France
echo $territory->name_as_it;                        // Francia
echo $territory->name_as_ja;                        // フランス

echo $repository->territories['FR']->first_day;     // mon
echo $repository->territories['EG']->first_day;     // sat
echo $repository->territories['BS']->first_day;     // sun

echo $repository->territories['AE']->weekend_start; // fri
echo $repository->territories['AE']->weekend_end;   // sat

本地化领土

可以通过 localize() 方法或所需区域的 localize() 方法获取本地化领土。

<?php

/* @var $repository \ICanBoogie\CLDR\Repository */

$territory = $repository->territories['FR'];

$localized_territory = $territory->localize('fr');
# or
$localized_territory = $repository->locales['fr']->localize($territory);

echo $territory->localize('fr')->name;   // France
echo $territory->localize('it')->name;   // Francia
echo $territory->localize('ja')->name;   // フランス

货币

货币由 Currency 实例表示。您可以自己创建实例或通过货币集合获取实例。

<?php

use ICanBoogie\CLDR\Currency;

/* @var $repository \ICanBoogie\CLDR\Repository */

$euro = new Currency($repository, 'EUR');
# or
$euro = $repository->currencies['EUR'];

本地化货币

可以使用 localize() 方法或所需地区的 localize() 方法获取本地化货币,这通常用于按照地区的惯例格式化货币。

<?php

use ICanBoogie\CLDR\Currency;

/* @var $repository \ICanBoogie\CLDR\Repository */

$currency = new Currency($repository, 'EUR');

$localized_currency = $currency->localize('fr');
# or
$localized_currency = $repository->locales['fr']->localize($currency);

echo $localized_currency->name;             // euro
echo $localized_currency->name(1);          // euro
echo $localized_currency->name(10);         // euros
echo $localized_currency->format(12345.67); // 12 345,67 €

持续集成

该项目由 GitHub actions 持续测试。

Tests Static Analysis

行为准则

本项目遵守 贡献者行为准则。通过参与本项目及其社区,您应遵守此准则。

贡献

有关详细信息,请参阅 CONTRIBUTING

许可证

icanboogie/cldr 采用 BSD-3-Clause 许可证发布。