首页 > 解决方案 > php ucfirst ucwords 讨论

问题描述

我只是想在需要处理与语言无关的 ucfirst 版本时分享我的经验。问题是当您将英文文本与日文、中文或其他语言混合时,例如在我的情况下,有时将瑞典文等与 ÅÄÖ 混合使用时,传统的 ucfirst 在将字符串转换为大写时存在问题。

然而,前一段时间我确实在堆栈溢出时偶然发现了以下代码片段:

function myucfirst($str) {
    $fc = mb_strtoupper(mb_substr($str, 0, 1));
    return $fc.mb_substr($str, 1);
}

它在大多数情况下都可以正常工作,但最近我还需要翻译使用 TCPDF 自动生成动态 pdf 中的文本。

这就是我想知道为什么 TCPDF 的文本有问题的时候。我在其他任何地方都没有问题,字符编码是 utf8,但还是变砖了。

在显示日语符号的汉字时,我只是使用上面的函数将单词大写,但突然在使用瑞典语时,当我需要大写 ÅÄÖ 时,我遇到了同样的砖块。

这让我意识到上述函数的问题在于它只查看第一个字符。ÅÄÖ 占用 2 个字母空间,汉字或日文字母占用 3 个字母空间,上面的函数没有考虑到导致 TCPDF 变砖。

为了提供更多上下文,当使用 TCPDF 生成 PDF 文档时,TCP 字体最终会出错,因为 gerneal mb_string 函数会将瑞典词 Övrigt 的第一个字符转换为“?�”vrigt,例如日语“?�� "のととろ,对于邻のトトロ(我的邻居 totoro。)这将使�的字体翻译无法正常工作。您需要将前两个字母 substr($str, 0,2) 的 ÅÄÖ 转换为能够正确转换字母。

此外,我不确定您是否看到我给出的代码示例,但由于中文或日文在其书写语言中都没有使用大写字母,因此我排除了每个需要 3 个字母空格的符号,因为它们根本不管理大写/小写。我真的不想排除它们,但是通过 mb_string 解析它们会导致 TCPDF 中出现类似的错误,因此,我的示例现在是一种解决方法,或者如果有人有更好的解决方案。

所以...我的方法是通过使用以下函数来解决上述问题。

function myucfirst($str) {
    if ($str[0] !== "?"){
        for($i = 1; $i <= 3; $i++){
            $first = substr($str, 0, $i);
            $first = mb_convert_case($first, MB_CASE_UPPER, "UTF-8");
            if ($first !== '?'){                
                $rest = substr($str, $i);
                break;
            }
        }
        if ($i < 3){
            $ret_string = $first . $rest;
        } else {
            $ret_string = $str;
        }
    } else {
        $ret_string = $str;
    }   
    return $ret_string;
}

感谢下面 Steven Pennys 的帮助,这是适用于瑞典语和日语/中文特殊字符的解决方案,即使需要使用库 TCPDF 的字符串来动态创建 PDF:

function myucfirst($str) {
    $ret_string = mb_convert_case($str, MB_CASE_TITLE, 'UTF-8');
    return $ret_string;
}

并随后对 ucwords 进行类似的修复

function myucwords($str){
    $str = trim($str);
    if (strpos($str, ' ') !== false){
        $str_arr = explode(' ', $str);
        foreach ($str_arr as $word){
            $ret_str .= isset($ret_str)? ' ' . myucfirst($word):myucfirst($word);
        }
    } else {
        $ret_str = myucfirst($str);
    }
    return $ret_str;
}

myucwords 使用第一个 myucfirst 来大写每个单词。

由于我没有作为开发人员或堆栈溢出贡献者的经验,您应该能够看到 3 个代码示例,如果有更好的方法来编写这些函数,我将不胜感激,但现在,对于那些有类似问题的人,请请享用!

/克里斯

标签: phpunicodemultilingualtcpdf

解决方案


您提供的示例很差,因为Övrigt输入与输出完全相同。所以我修改了这个例子,以便它们有用。见下文:

<?php
# example 1
$s1 = mb_convert_case('åäö', MB_CASE_TITLE);
# example 2
$s2 = mb_convert_case('övrigt', MB_CASE_TITLE);
# exmaple 3
$s3 = mb_convert_case('隣のトトロ', MB_CASE_TITLE);
# print
var_dump($s1 == 'Åäö', $s2 == 'Övrigt', $s3 == '隣のトトロ');

php.ini请注意,如果还没有,您将需要它:

extension = mbstring

https://php.net/function.mb-convert-case


推荐阅读