欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

神秘化的本地化:所有人的Php-Intl

程序员文章站 2024-03-19 17:56:34
...
神秘化的本地化:所有人的Php-Intl

Most applications perform locale aware operations like working with texts, dates, timezones, etc. The PHP Intl extension provides a good API for accessing the widely known ICU library’s functions.

大多数应用程序执行区域感知操作,例如处理文本,日期,时区等。PHPIntl扩展提供了一个很好的API,可用于访问广为人知的ICU库功能。

安装 (Installation)

The extension is installed by default on PHP 5.3 and above. You can look for it by running the following command:

该扩展默认情况下安装在PHP 5.3及更高版本上。 您可以通过运行以下命令来查找它:

php -m | grep 'intl'

If the extension is not present, you can install it manually by following the installation guide. If you’re using Ubuntu, you can directly run the following commands.

如果扩展名不存在,则可以按照安装指南手动进行安装 。 如果您使用的是Ubuntu,则可以直接运行以下命令。

sudo apt-get update
sudo apt-get install php5-intl

If you’re using PHP7 on your machine, you need to add the (ppa:ondrej/php) PPA, update your system and install the Intl extension.

如果您在计算机上使用PHP7,则需要添加( ppa:ondrej/php )PPA,更新系统并安装Intl扩展。

# Add PPA
sudo add-apt-repository ppa:ondrej/php-7.0
# Update repository index
sudo apt-get update
# install extension
sudo apt-get install php7.0-intl

讯息格式 (Message Formatting)

Most modern applications are built with localization in mind. Sometimes, the message is a plain string with variable placeholders, other times it’s a complex pluralized string.

大多数现代应用程序的构建都考虑到了本地化。 有时,消息是带有可变占位符的纯字符串,而其他时候,消息是复杂的复数字符串。

简单讯息 (Simple Messages)

We’re going to start with a simple message containing a placeholder. Placeholders are patterns enclosed in curly braces. Here is an example:

我们将从包含占位符的简单消息开始。 占位符是用大括号括起来的模式。 这是一个例子:

var_dump(
    MessageFormatter::formatMessage(
        "en_US",
        "I have {0, number, integer} apples.",
        [ 3 ]
    )
);
// output

string(16) "I have 3 apples."

The arguments passed to the MessageFormatter::formatMessage method are:

传递给MessageFormatter::formatMessage方法的参数为:

  • The message locale.

    消息语言环境。
  • String message.

    字符串消息。
  • Placeholder data.

    占位符数据。

The {0, number, integer} placeholder will inject the first item of the data array as a numberinteger (see the table below for the list of options). We can also use named arguments for placeholders. The example below will output the same result.

{0, number, integer}占位符将以number - integer的形式插入数据数组的第一项(有关选项列表,请参见下表)。 我们还可以将命名参数用作占位符。 下面的示例将输出相同的结果。

var_dump(
    MessageFormatter::formatMessage(
        "en_US",
        "I have {number_apples, number, integer} apples.",
        [ 'number_apples' => 3 ]
    )
);

Different languages have different numeral systems, like Arabic, indian, etc.

不同的语言具有不同的数字系统,例如阿拉伯语印度 等。

神秘化的本地化:所有人的Php-Intl

The previous example is targeting the en_US locale. Let’s change it to ar to see the difference.

前面的示例以en_US语言环境为目标。 让我们将其更改为ar可以看到不同之处。

var_dump(
    MessageFormatter::formatMessage(
        "ar",
        "I have {number_apples, number, integer} apples.",
        [ 'number_apples' => 3 ]
    )
);
string(17) "I have ٣ apples."

We can also change it to Bengali locale (bn).

我们还可以将其更改为孟加拉语言环境( bn )。

var_dump(
    MessageFormatter::formatMessage(
        "bn",
        "I have {number_apples, number, integer} apples.",
        [ 'number_apples' => 3 ]
    )
);
string(18) "I have ৩ apples."

So far, we’ve only worked with numbers. Let’s take a look at other types that we can use.

到目前为止,我们仅处理数字。 让我们看一下可以使用的其他类型。

$time = time();
var_dump( MessageFormatter::formatMessage(
    "en_US",
    "Today is {0, date, full} - {0, time}",
    array( $time )
) );
string(47) "Today is Wednesday, April 6, 2016 - 11:21:47 PM"
var_dump( MessageFormatter::formatMessage(
    "en_US",
    "duration: {0, duration}",
    array( $time )
) );
string(23) "duration: 405,551:27:58"

We can also spell out the passed numbers.

我们还可以拼出所传递的数字。

var_dump( MessageFormatter::formatMessage(
    "en_US",
    "I have {0, spellout} apples",
    array( 34 )
) );
string(25) "I have thirty-four apples"

It also works on different locales. Here is an example using the Arabic language.

它还适用于不同的语言环境。 这是使用阿拉伯语的示例。

var_dump( MessageFormatter::formatMessage(
    "ar",
    "لدي {0, spellout} تفاحة",
    array( 34 )
) );
string(44) "لدي أربعة و ثلاثون تفاحة"
argType argStyle
number integer, currency, percent
date short, medium, long, full
time short, medium, long, full
spellout short, medium, long, full
ordinal
duration
argType argStyle
整数,货币,百分比
日期 短,中,长,满
时间 短,中,长,满
拼写 短,中,长,满
序数
持续时间

多元化 (Pluralization)

An important part of localizing our application is to manage plural messages to make our UI as intuitive as possible. The apples example above will do the job. Here’s how messages should look like in this case.

本地化我们的应用程序的重要部分是管理多个消息,以使我们的UI尽可能直观。 上面的苹果示例将完成此任务。 在这种情况下,消息显示如下。

  • (number_apples = 0): I have no apples.

    ( number_apples = 0):我没有苹果。

  • (number_apples = 1): I have one apple.

    ( number_apples = 1):我有一个苹果。

  • (number_apples > 1): I have X apples.

    ( number_apples > 1):我有X个苹果。

var_dump( MessageFormatter::formatMessage(
    "en_US",
    'I have {number_apples, plural, =0{no apples} =1{one apple} other{# apples}}',
    array('number_apples' => 10)
) );
// number_apples = 0
string(16) "I have no apples"

// number_apples = 1
string(16) "I have one apple"

// number_apples = 10
string(16) "I have 10 apples"

The syntax is really straightforward, and most pluralization packages adopt this syntax. Check the documentation for more details.

该语法确实非常简单,大多数复数软件包都采用此语法。 查看文档以获取更多详细信息。

{data, plural, offsetValue =value{message}... other{message}}
  • data: value index.

    data :值索引。

  • plural: argType.

    plural :argType。

  • offsetValue: the offset value is optional(offset:value). It subtracts the offset from the value.

    offsetValue :偏移值是可选的( offset:value )。 它从值中减去偏移量。

  • =value{message}: value to test for equality, and the message between curly braces. We can repeat this part multiple times (=0{no apples} =1{one apple} =2{two apple}).

    =value{message} :用于测试是否相等的值,以及花括号之间的消息。 我们可以重复此部分多次( =0{no apples} =1{one apple} =2{two apple} )。

  • other{message}: The default case, like in a switch - case statement. The # character may be used the inject the data value.

    other{message} :默认大小写,例如switch - case语句。 #字符可用于注入data值。

选择项 (Choices)

In some cases, we need to print a different message for every range. The example below does this.

在某些情况下,我们需要为每个范围打印不同的消息。 下面的示例执行此操作。

var_dump( MessageFormatter::formatMessage(
    "en_US",
    'The value of {0,number} is {0, choice,
                                        0 # between 0 and 19 |
                                        20 # between 20 and 39 |
                                        40 # between 40 and 59 |
                                        60 # between 60 and 79 |
                                        80 # between 80 and 100 |
                                        100 < more than 100 }',
    array(60)
) );
string(38) "The value of 60 is between 60 and 79 "

The argType in this case is set to choice, and this is the syntax format:

在这种情况下, argType设置为choice ,这是语法格式:

{value, choice, choiceStyle}

The official definition from the ICU documentation is:

ICU文档中的正式定义是:

choiceStyle = number separator message ('|' number separator message)*

number = normal_number | ['-']  ∞ (U+221E, infinity)
normal_number = double value (unlocalized ASCII string)

separator = less_than | less_than_or_equal
less_than = '<'
less_than_or_equal = '#' |  ≤ (U+2264)

Note: ICU developers discourage the use of the choice type.

注意 :ICU开发人员不鼓励使用选择类型。

选择 (Select)

Sometimes we need something like the select option UI component. Profile pages use this to update the UI messages according to the user’s gender, etc. Here’s an example:

有时我们需要诸如选择选项UI组件之类的东西。 个人资料页面使用它来根据用户的性别等更新UI消息。这是一个示例:

var_dump( MessageFormatter::formatMessage(
    "en_US",
    "{gender, select, ".
      "female {She has some apples} ".
      "male {He has some apples.}".
      "other {It has some apples.}".
    "}",
    array('gender' => 'female')
) );
string(19) "She has some apples"

The pattern is defined as follows:

该模式定义如下:

{value, select, selectStyle}

// selectStyle
selectValue {message} (selectValue {message})*

The message argument may contain other patterns like choice and plural. The next part will explain a complex example where we combine multiple patterns. Check the ICU documentation for more details.

message参数可以包含其他模式,例如选择和复数。 下一部分将解释一个复杂的示例,其中我们组合了多种模式。 有关更多详细信息,请参阅ICU文档

复杂案例 (Complex Cases)

So far, we’ve seen some simple examples like pluralization, select, etc. Some cases are more complex than others. The ICU documentation has a very good example illustrating this. We’ll insert part by part to make it simpler to grasp.

到目前为止,我们已经看到了一些简单的示例,例如复数,选择等。某些情况比其他情况更复杂。 ICU文档中有一个很好的例子来说明这一点。 我们将逐部分插入,以使其更易于掌握。

var_dump( MessageFormatter::formatMessage(
    "en_US",
    "{gender_of_host, select, ".
      "female {She has a party} ".
      "male {He has some apples.}".
      "other {He has some apples.}".
    "}",
    array('gender_of_host' => 'female', "num_guests" => 5, 'host' => "Hanae", 'guest' => 'Younes' )
) );

This is the same example we used before, but instead of using a simple message, we customize it depending on the num_guests value (talking about pluralization here).

这是我们之前使用的示例,但是我们不使用简单的消息,而是根据num_guests值(在此谈论复数) num_guests自定义。

var_dump( MessageFormatter::formatMessage(
    "en_US",
    "{gender_of_host, select, ".
      "female {".
        "{num_guests, plural, offset:1 ".
          "=0 {{host} does not have a party.}".
          "=1 {{host} invites {guest} to her party.}".
          "=2 {{host} invites {guest} and one other person to her party.}".
          "other {{host} invites {guest} and # other people to her party.}}}".
      "male {He has some apples.}".
      "other {He has some apples.}}",
    array('gender_of_host' => 'female', "num_guests" => 5, 'host' => "Hanae", 'guest' => 'Younes' )
) );

Notice that we’re using the offset:1 to remove one guest from the num_guests value.

请注意,我们正在使用offset:1num_guests值中删除一个来宾。

string(53) "Hanae invites Younes and 4 other people to her party."

Here’s the full snippet of this example.

这是此示例的完整代码段。

var_dump( MessageFormatter::formatMessage(
    "en_US",
    "{gender_of_host, select, ".
      "female {".
        "{num_guests, plural, offset:1 ".
          "=0 {{host} does not have a party.}".
          "=1 {{host} invites {guest} to her party.}".
          "=2 {{host} invites {guest} and one other person to her party.}".
          "other {{host} invites {guest} and # other people to her party.}}}".
      "male {".
        "{num_guests, plural, offset:1 ".
          "=0 {{host} does not have a party.}".
          "=1 {{host} invites {guest} to his party.}".
          "=2 {{host} invites {guest} and one other person to his party.}".
          "other {{host} invites {guest} and # other people to his party.}}}".
      "other {".
        "{num_guests, plural, offset:1 ".
          "=0 {{host} does not have a party.}".
          "=1 {{host} invites {guest} to their party.}".
          "=2 {{host} invites {guest} and one other person to their party.}".
          "other {{host} invites {guest} and # other people to their party.}}}}",
    array('gender_of_host' => 'female', "num_guests" => 5, 'host' => "Hanae", 'guest' => 'Younes' )
) );

Change the number of guests to test all message types.

更改来宾的数量以测试所有消息类型。

// num_guests = 2
string(55) "Hanae invites Younes and one other person to her party."

// num_guests = 1
string(34) "Hanae invites Younes to her party."

// num_guests = 0
string(28) "Hanae does not have a party."

讯息解析 (Message Parsing)

There’s not much to say about parsing messages; we use the pattern we used for formatting to extract data from an output message.

解析消息没有什么可说的。 我们使用用于格式化的模式从输出消息中提取数据。

$messageFormater = new MessageFormatter("en_US", 'I have {0, number}');
var_dump( $messageFormater->parse("I have 10 apples") );
array(1) {
  [0]=>
  int(10)
}

Check the documentation for more details about message parsing.

查看文档以获取有关消息解析的更多详细信息。

结论 (Conclusion)

In this introductory post, we learned about localizing our messages using the PHP Intl extension. The next part will cover formatting numbers and dates, and how to work with calendars. If you have any questions about what we’ve covered so far, you can post them in the comments below!

在这篇介绍性文章中,我们学习了如何使用PHP Intl扩展来本地化消息。 下一部分将介绍格式化数字和日期以及如何使用日历。 如果您对我们目前所涵盖的内容有任何疑问,可以在下面的评论中发布!

翻译自: https://www.sitepoint.com/localization-demystified-understanding-php-intl/