PHP Intl函数不适用于某些国家/地区

PHP Intl函数不适用于某些国家/地区,php,localization,icu,intl,Php,Localization,Icu,Intl,试图从语言代码中获取语言名称,我运行 function test($local, $fallback) { $bundle = \ResourceBundle::create($local, 'ICUDATA-lang', $fallback); if ($bundle === null) { return "$local bundle not found"; } $var = $bundle->get('Languages',$fallba

试图从语言代码中获取语言名称,我运行

function test($local, $fallback)
{
    $bundle = \ResourceBundle::create($local, 'ICUDATA-lang', $fallback);
    if ($bundle === null) {
        return "$local bundle not found";
    }
    $var = $bundle->get('Languages',$fallback);
    return $var->get('fr',$fallback);
}

$locals = ['en', 'en_US', 'foo', 'en_AU', 'en_NZ'];

foreach ($locals as $local) {
    var_dump(test($local, true));
}
echo PHP_EOL;
foreach ($locals as $local) {
    var_dump(test($local, false));
}
它为澳大利亚和新西兰返回null,表示Intl错误为

无法加载资源元素“fr”:U\U缺少\U资源\U错误

\ResourceBundle::create functions的第三个参数用于回调,这意味着它应该回退到其父语言环境。有趣的是,这是en_001

是虫子还是我错过了什么

背景 在ICU数据目录中,注意到您在发布分支而不是主分支上,没有en_US和en_UK的文件。在主分支上,您可以找到一个en_GB文件,它似乎是正确的区域设置代码,而不是UK

虽然我不能说为什么en_US不在我绝对期待的范围内,正如你所做的那样,你的所有测试结果都是法语,你实际上没有加载正确的ICU路径,而是因为找不到该路径,根路径被加载

你已经用en_foobar证明了这一点。如果您尝试加载该数据目录中不存在的任何其他无意义的语言环境,则同样适用于en_US和en_UK,因为它们都不存在,如前所述

作为旁注:我认为您可能误解了回退参数。这样,如果无法加载语言,则会加载回退语言,而不是直接在父级上请求对其请求的任何数据

代码示例 为了让我说的更清楚一点,这里有一些例子

使用无意义的区域设置加载总是加载整个目录数据,因此您可以访问所有根数据:

$bundle = \ResourceBundle::create('stackoverflow-is-great', 'ICUDATA-lang', true);
var_dump($bundle->get('Languages')->get('fr')); // string(6) "French"
var_dump($bundle->get('Languages')->get('de')); // string(6) "German"
从不存在的en_NZ加载子语言:

从en_NZ加载确实存在的子语言:

简而言之:它实际上按照预期工作,在可用的地方提供数据,在没有可用的地方提供数据

调试 我怎么知道的?基于PHP ResourceBundle文档页面。我添加了一个深度输出,并有一个非常方便的调试功能:

function t($rb, $depth = 0) {
    foreach($rb as $k => $v) {
        echo str_repeat('->', $depth);
        if(is_object($v)) {
            print_r($v);
            var_dump($k);
            t($v, ++$depth);
        } else {
            var_dump($k . " " . $v);
        }
    }
}
$rb = new ResourceBundle('en_UK', 'ICUDATA-lang', true);
var_dump($rb->get('Languages')->get('fr'));

t($rb);
这会打印出一个很长的文件,这就是为什么我不在这里添加它的原因,它的输出看起来很像根数据

最后一个旁注:en_GB似乎也是,但我不确定会产生什么影响

TL;DR:前三个区域设置在数据集中并不存在,因此根数据被加载,en_NZ和en_AU工作正常。

Background 在ICU数据目录中,注意到您在发布分支而不是主分支上,没有en_US和en_UK的文件。在主分支上,您可以找到一个en_GB文件,它似乎是正确的区域设置代码,而不是UK

虽然我不能说为什么en_US不在我绝对期待的范围内,正如你所做的那样,你的所有测试结果都是法语,你实际上没有加载正确的ICU路径,而是因为找不到该路径,根路径被加载

你已经用en_foobar证明了这一点。如果您尝试加载该数据目录中不存在的任何其他无意义的语言环境,则同样适用于en_US和en_UK,因为它们都不存在,如前所述

作为旁注:我认为您可能误解了回退参数。这样,如果无法加载语言,则会加载回退语言,而不是直接在父级上请求对其请求的任何数据

代码示例 为了让我说的更清楚一点,这里有一些例子

使用无意义的区域设置加载总是加载整个目录数据,因此您可以访问所有根数据:

$bundle = \ResourceBundle::create('stackoverflow-is-great', 'ICUDATA-lang', true);
var_dump($bundle->get('Languages')->get('fr')); // string(6) "French"
var_dump($bundle->get('Languages')->get('de')); // string(6) "German"
从不存在的en_NZ加载子语言:

从en_NZ加载确实存在的子语言:

简而言之:它实际上按照预期工作,在可用的地方提供数据,在没有可用的地方提供数据

调试 我怎么知道的?基于PHP ResourceBundle文档页面。我添加了一个深度输出,并有一个非常方便的调试功能:

function t($rb, $depth = 0) {
    foreach($rb as $k => $v) {
        echo str_repeat('->', $depth);
        if(is_object($v)) {
            print_r($v);
            var_dump($k);
            t($v, ++$depth);
        } else {
            var_dump($k . " " . $v);
        }
    }
}
$rb = new ResourceBundle('en_UK', 'ICUDATA-lang', true);
var_dump($rb->get('Languages')->get('fr'));

t($rb);
这会打印出一个很长的文件,这就是为什么我不在这里添加它的原因,它的输出看起来很像根数据

最后一个旁注:en_GB似乎也是,但我不确定会产生什么影响

TL;DR:前三个区域设置在数据集中并不存在,因此根数据被加载,en_NZ和en_AU的工作方式与它们应该的一样。

您从以下方面获得了什么:

->获取“语言”->获取$lang

不会受到加载存储库时有无回退的影响

$locals=['en','en_US','foo','en_AU','en_NZ']

en、en_AU和en_NS是直接的:因此它们都可以加载或不加载回退。 en_US未定义,但以en_开头。这意味着它给了对手 tunity加载en_US,这将依赖于en。如果使用en_FooBar,情况也是如此。如果你试着用“bas_il_ic”,它会用“bas”。 foo根本没有定义,不能回退,因此这意味着创建ResourceBundle不会因为fallback=true而失败,但是,您可以从中获得的只是null。 这意味着fallback参数只允许在ResourceBundle::create时对区域设置进行某种严格/非严格匹配,但要理解区域设置xx_YY的父级是xx。它与%%Parent{xxxxxx}定义引起的继承无关,它不遵循上面定义的父语言环境的原则,而是跨语言环境共享公共定义的一种方式

因此,您的结果和文档都是正确的:

如果回退是正确的:

“en”:法语,因为语言环境en存在,法语是语言环境的一部分 “en_US”:法语,因为没有定义语言环境en_US,它依赖于en,法语是其中的一部分 “foo”:NULL,因为区域设置foo不存在,也不能回退。 “en_AU”:NULL,因为locale扩展了,但它们都没有定义fr。 “en_NZ”:与en_AU相同。 如果回退是错误的:

“en”:法语,因为语言环境en存在,法语是语言环境的一部分 “en_US”:未找到en_US bundle:很明显,en_US确实没有定义。 'foo':找不到foo包:很明显,foo确实没有定义。 “en_AU”:与回退策略的解释相同。 “en_NZ”:与回退策略相同的解释是正确的。 你可能会问自己: 为什么语言环境xx_YY的ICU语言数据不继承xx的语言数据?这对所有地区都有效,不仅仅是英语地区

PHP与ICU库提供的内容一致,但您可能会质疑ICU的内部数据。

您从以下方面获得了什么:

->获取“语言”->获取$lang

不会受到加载存储库时有无回退的影响

$locals=['en','en_US','foo','en_AU','en_NZ']

en、en_AU和en_NS是直接的:因此它们都可以加载或不加载回退。 en_US未定义,但以en_开头。这意味着它提供了加载en_US的机会,这将依赖于en。如果使用en_FooBar,情况也是如此。如果你试着用“bas_il_ic”,它会用“bas”。 foo根本没有定义,不能回退,因此这意味着创建ResourceBundle不会因为fallback=true而失败,但是,您可以从中获得的只是null。 这意味着fallback参数只允许在ResourceBundle::create时对区域设置进行某种严格/非严格匹配,但要理解区域设置xx_YY的父级是xx。它与%%Parent{xxxxxx}定义引起的继承无关,它不遵循上面定义的父语言环境的原则,而是跨语言环境共享公共定义的一种方式

因此,您的结果和文档都是正确的:

如果回退是正确的:

“en”:法语,因为语言环境en存在,法语是语言环境的一部分 “en_US”:法语,因为没有定义语言环境en_US,它依赖于en,法语是其中的一部分 “foo”:NULL,因为区域设置foo不存在,也不能回退。 “en_AU”:NULL,因为locale扩展了,但它们都没有定义fr。 “en_NZ”:与en_AU相同。 如果回退是错误的:

“en”:法语,因为语言环境en存在,法语是语言环境的一部分 “en_US”:未找到en_US bundle:很明显,en_US确实没有定义。 'foo':找不到foo包:很明显,foo确实没有定义。 “en_AU”:与回退策略的解释相同。 “en_NZ”:与回退策略相同的解释是正确的。 你可能会问自己: 为什么语言环境xx_YY的ICU语言数据不继承xx的语言数据?这对所有地区都有效,不仅仅是英语地区

PHP与ICU库提供的一致,但您可能会质疑ICU的内部数据。

ResourceBundle::create和ResourceBundle::get方法都有回退参数。但是只有第一个方法实际使用这个参数,而get方法只是忽略它。这不是本文中所解释的

退路

允许区域设置完全匹配还是回退到父区域设置

使用该包,它可以按预期工作

<?php
require_once "vendor/autoload.php";

use Salarmehr\Cosmopolitan\Intl;

function test($local)
{
    return Cosmo::create($local)->get('ICUDATA-lang','Languages','fr');
}

$locals = ['en', 'en_US', 'foo', 'en_AU', 'en_NZ'];

foreach ($locals as $local) {
    var_dump(test($local));
}
ResourceBundle::create和ResourceBundle::get方法都有回退参数。但是只有第一个方法实际使用这个参数,而get方法只是忽略它。这不是本文中所解释的

退路

允许区域设置完全匹配还是回退到父区域设置

使用该包,它可以按预期工作

<?php
require_once "vendor/autoload.php";

use Salarmehr\Cosmopolitan\Intl;

function test($local)
{
    return Cosmo::create($local)->get('ICUDATA-lang','Languages','fr');
}

$locals = ['en', 'en_US', 'foo', 'en_AU', 'en_NZ'];

foreach ($locals as $local) {
    var_dump(test($local));
}

这个ResourceBundle是什么类的?@delboy1978uk这个ResourceBundle是什么类的?@delboy1978uk谢谢你的尝试。问题是为什么回退参数不起作用。该参数被解释为区域设置是否应与e匹配
允许直接或回退到父语言环境。在每个本地文件中都有父本地文件,并且它们的方式是扩展其父本地文件并仅覆盖与父本地文件不同的值。因此,提供一个有效的区域设置时,如果子区域设置中的键未被重写,它应该回退到其父区域设置。这是我的观点,第一个旁注我不清楚这基本上是一个问题,因此感谢澄清:文档说区域设置应该完全匹配还是允许回退到父区域设置。从我观察到的情况来看,这正是所发生的。是什么让你产生了子区域扩展的想法!家长?谢谢你的尝试。问题是为什么回退参数不起作用。该参数被解释为区域设置应完全匹配还是允许回退到父区域设置。在每个本地文件中都有父本地文件,并且它们的方式是扩展其父本地文件并仅覆盖与父本地文件不同的值。因此,提供一个有效的区域设置时,如果子区域设置中的键未被重写,它应该回退到其父区域设置。这是我的观点,第一个旁注我不清楚这基本上是一个问题,因此感谢澄清:文档说区域设置应该完全匹配还是允许回退到父区域设置。从我观察到的情况来看,这正是所发生的。是什么让你产生了子区域扩展的想法!家长?是的,这就是示例中演示的内容。It回退选项不起作用。文件化的方法是有用的。我扩展了答案。选项的工作方式如文件所述,但根据命名约定,父语言环境的概念是:en_XX=>en与ICU的内部继承机制不同,例如,en_AU扩展了en_001,但没有一个与en共享。所以你应该明确质疑ICU的数据定义。PHP与此无关。是的,这就是示例中演示的内容。It回退选项不起作用。文件化的方法是有用的。我扩展了答案。选项的工作方式如文件所述,但根据命名约定,父语言环境的概念是:en_XX=>en与ICU的内部继承机制不同,例如,en_AU扩展了en_001,但没有一个与en共享。所以你应该明确质疑ICU的数据定义。PHP与此无关。
string(6) "French"
string(6) "French"
NULL
string(6) "French"
string(6) "French"