我想显示数组中的值列表,并使其可翻译。我选择的翻译方法是获取文本。我正在尝试做的一个例子是将可变长度数组转换为:
$array = ('apple', 'plum', 'watermelon', [...]);
变成像apple, plum and watermelon
这样的字符串。
只用英语做不会有问题,但使其可翻译是,因为其他语言可能不一定使用逗号来分隔值和/或可能没有单词"and",而倒数第二个和最后一个值之间没有逗号。如果我知道数组总是有 3 个值,我可以很容易地做到:
sprintf(gettext("%s, %s and %s"), $array[0], $array[1], $array[2]);
问题是数组的长度可以变化。如何从可变长度数组制作可翻译列表?
编辑:
也许我没有说清楚,但其他语言可能会以不同的方式处理列表。例如,一种语言可能像1 and 2, 3, 4
一样显示列表,另一种语言可能像1, 2, 3, 4
一样显示它,另一种语言可能在列表之前和之后有额外的内容,等等。
这可能会有所帮助,但就预先知道使用哪种类型的分隔符和胶水而言,它可能有一个列表并能够将语言作为使用其中哪一种的参考?
<?php
/**
* @author - Sephedo
* @for - Mike @ Stackoverflow
* @question - http://stackoverflow.com/questions/18751650/making-a-variable-length-list-translatable
*/
echo arr2str( array('apple', 'banana', 'peach', 'pear', 'orange') );
// This function will convert the array to a formatted string.
function arr2str( array $array, $separator = ', ', $glue = ' and ' )
{
if( count( $array ) == 1 ) return (string) $array; // If there is only one item return the item.
$last = array_pop( $array ); // get the last element of the array and remove from the array.
return implode( $separator, $array ) . "$glue$last"; // implode the array by the seperator and add the last element.
}
?>
这将返回
string 'apple, banana, peach, pear and orange' (length=38)
您可以执行以下操作:
- 遍历数组并
- 检查迭代是否是最后一个
- 如果是,则在变量前面附加一个
and
法典:
function makeTrans($array)
{
$str = '';
for ($i=0; $i < count($array); $i++) {
if($i == count($array) - 1) {
$str .= "and ".$array[$i];
}
else {
$str .= $array[$i]." ";
}
}
return $str;
}
用法:
$array = array('apple', 'plum', 'watermelon', 'foo', 'bar', 'baz', 'baq');
echo makeTrans($array);
输出:
apple plum watermelon foo bar baz and baq
看看它的实际效果!
如果您想更改分隔符的位置,请尝试此修改版本
<?php
/**
* @author - Sephedo
* @for - Mike @ Stackoverflow
* @question - http://stackoverflow.com/questions/18751650/making-a-variable-length-list-translatable
*/
var_dump( arr2str( array('apple', 'banana', 'peach', 'pear', 'orange') ) );
var_dump( arr2str( array('apple', 'banana', 'peach', 'pear', 'orange'), 1 ) );
var_dump( arr2str( array('apple', 'banana', 'peach', 'pear', 'orange'), 3 ) );
var_dump( arr2str( array('apple', 'banana', 'peach', 'pear', 'orange'), 4 ) );
// @array - the array to parse
// @pos - the position to put the glue
// @separator - aka the comma separator
// @glue - aka the and word
function arr2str( array $array, $pos=null, $separator = ', ', $glue = ' and ' )
{
if( count( $array ) == 1 ) return (string) $array; // If there is only one item return the item.
if( is_null( $pos ) ) $pos = count( $array ) - 1; // get the default and position aka last.
$start = array_slice( $array, 0, $pos ); $end = array_slice( $array, $pos, count( $array ) + 1 );
return implode( $separator, $start ) . $glue . implode( $separator, $end );
}
?>
这将导致
string 'apple, banana, peach, pear and orange' (length=37)
string 'apple and banana, peach, pear, orange' (length=37)
string 'apple, banana, peach and pear, orange' (length=37)
string 'apple, banana, peach, pear and orange' (length=37)
我想到的一种方法是这样的:
function array_to_str($array) {
$two_values = _("%s and %s");
$three_values = _("%s, %s and %s");
$separator = _(", ");
if (count($array) == 1) {
return $array[0];
}
if (count($array) == 2) {
return sprintf($two_values, $array[0], $array[1]);
}
$prev = '';
for ($i = 0; $i < count($array) - 2; $i++) {
$prev .= $array[$i];
if ($i < count($array) - 3) {
$prev .= $separator;
}
}
return sprintf(
$three_values,
$prev,
$array[count($array) - 2],
$array[count($array) - 1]
);
}
$arrays[] = array('apple');
$arrays[] = array('apple', 'plum');
$arrays[] = array('apple', 'plum', 'watermelon');
$arrays[] = array('apple', 'plum', 'watermelon', 'lemon');
foreach ($arrays as $array) {
echo array_to_str($array) . PHP_EOL;
}
这将输出:
apple
apple and plum
apple, plum and watermelon
apple, plum, watermelon and lemon
如果语言使用列表格式1 and 2, 3, 4, 5, 6
,则翻译者可以通过翻译来克服这一点
$three_values = "%3$s and %2$s, %1$s";
不幸的是,这样做,列表将无序。该字符串将输出6 and 5, 1, 2, 3, 4
。
但是,通过Google翻译中当前定义的语言,没有一种语言可以将"and"的位置更改为倒数第二的位置。从右到左的语言在从左到右阅读时将其放在第一个元素之后,但由于它是从右到左,因此它实际上处于正确的(倒数第二个)位置。
使用此方法还可以克服以非标准方式显示其列表的语言:
(Korean) 1, 2, 3, 4 <-- only commas are used
(Italian) 1, 2, 3 e 4, <-- extra comma at the end
(Chinese) 1,2,3和4的 <-- extra 的 at the end
(Hungarian) Az 1., 2., 3. és 4. <-- extra A at the beginning for 2 numbers, Az at the beginning for 3 or more numbers
最后一个可以使用上面的函数来完成,如下所示:
$two_values = "A %s és %s";
$three_values = "Az %s, %s és %s";
$separator = ", ";
假设您的数字格式正确,这将输出:
A 1. és 2.
Az 1., 2. és 3.
Az 1., 2., 3. és 4.