feat: 安装pinyin库

master
yin5th 2023-10-12 15:48:38 +08:00
parent fc32752815
commit b073e44bce
32 changed files with 252325 additions and 7 deletions

View File

@ -41,7 +41,8 @@
"topthink/think-swoole": "^3.1",
"phpoffice/phpspreadsheet": "^1.19",
"yly-openapi/yly-openapi-sdk": "^1.0",
"mk-j/php_xlsxwriter": "^0.39.0"
"mk-j/php_xlsxwriter": "^0.39.0",
"overtrue/pinyin": "^5.0"
},
"require-dev": {
"symfony/var-dumper": "^4.2",

61
server/composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "d9ec16906092528de6a3bf06cb281ef3",
"content-hash": "5e95bbb3ddb2be6e7a5e7df7cab9e886",
"packages": [
{
"name": "adbario/php-dot-notation",
@ -2060,6 +2060,65 @@
},
"time": "2021-03-01T04:13:24+00:00"
},
{
"name": "overtrue/pinyin",
"version": "5.2.2",
"dist": {
"type": "zip",
"url": "https://mirrors.tencent.com/repository/composer/overtrue/pinyin/5.2.2/overtrue-pinyin-5.2.2.zip",
"reference": "1cb6fdfe0c90d1895bb2f877a33ab2c0b58cb21c",
"shasum": ""
},
"require": {
"php": ">=8.0.2"
},
"require-dev": {
"brainmaestro/composer-git-hooks": "^2.7",
"friendsofphp/php-cs-fixer": "^3.2",
"laravel/pint": "^1.10",
"nunomaduro/termwind": "^1.13",
"phpunit/phpunit": "^10.1"
},
"bin": [
"bin/pinyin"
],
"type": "library",
"extra": {
"hooks": {
"pre-commit": [
"composer pint",
"composer test"
],
"pre-push": [
"composer pint",
"composer test"
]
}
},
"autoload": {
"psr-4": {
"Overtrue\\Pinyin\\": "src/"
}
},
"license": [
"MIT"
],
"authors": [
{
"name": "overtrue",
"email": "anzhengchao@gmail.com",
"homepage": "http://github.com/overtrue"
}
],
"description": "Chinese to pinyin translator.",
"homepage": "https://github.com/overtrue/pinyin",
"keywords": [
"Chinese",
"Pinyin",
"cn2pinyin"
],
"time": "2023-09-27T08:07:28+00:00"
},
{
"name": "overtrue/socialite",
"version": "2.0.23",

120
server/vendor/bin/pinyin vendored Normal file
View File

@ -0,0 +1,120 @@
#!/usr/bin/env php
<?php
/**
* Proxy PHP file generated by Composer
*
* This file includes the referenced bin path (../overtrue/pinyin/bin/pinyin)
* using a stream wrapper to prevent the shebang from being output on PHP<8
*
* @generated
*/
namespace Composer;
$GLOBALS['_composer_bin_dir'] = __DIR__;
$GLOBALS['_composer_autoload_path'] = __DIR__ . '/..'.'/autoload.php';
if (PHP_VERSION_ID < 80000) {
if (!class_exists('Composer\BinProxyWrapper')) {
/**
* @internal
*/
final class BinProxyWrapper
{
private $handle;
private $position;
private $realpath;
public function stream_open($path, $mode, $options, &$opened_path)
{
// get rid of phpvfscomposer:// prefix for __FILE__ & __DIR__ resolution
$opened_path = substr($path, 17);
$this->realpath = realpath($opened_path) ?: $opened_path;
$opened_path = $this->realpath;
$this->handle = fopen($this->realpath, $mode);
$this->position = 0;
return (bool) $this->handle;
}
public function stream_read($count)
{
$data = fread($this->handle, $count);
if ($this->position === 0) {
$data = preg_replace('{^#!.*\r?\n}', '', $data);
}
$this->position += strlen($data);
return $data;
}
public function stream_cast($castAs)
{
return $this->handle;
}
public function stream_close()
{
fclose($this->handle);
}
public function stream_lock($operation)
{
return $operation ? flock($this->handle, $operation) : true;
}
public function stream_seek($offset, $whence)
{
if (0 === fseek($this->handle, $offset, $whence)) {
$this->position = ftell($this->handle);
return true;
}
return false;
}
public function stream_tell()
{
return $this->position;
}
public function stream_eof()
{
return feof($this->handle);
}
public function stream_stat()
{
return array();
}
public function stream_set_option($option, $arg1, $arg2)
{
return true;
}
public function url_stat($path, $flags)
{
$path = substr($path, 17);
if (file_exists($path)) {
return stat($path);
}
return false;
}
}
}
if (
(function_exists('stream_get_wrappers') && in_array('phpvfscomposer', stream_get_wrappers(), true))
|| (function_exists('stream_wrapper_register') && stream_wrapper_register('phpvfscomposer', 'Composer\BinProxyWrapper'))
) {
include("phpvfscomposer://" . __DIR__ . '/..'.'/overtrue/pinyin/bin/pinyin');
exit(0);
}
}
include __DIR__ . '/..'.'/overtrue/pinyin/bin/pinyin';

View File

@ -53,6 +53,7 @@ return array(
'Psr\\Cache\\' => array($vendorDir . '/psr/cache/src'),
'PhpOffice\\PhpSpreadsheet\\' => array($vendorDir . '/phpoffice/phpspreadsheet/src/PhpSpreadsheet'),
'Overtrue\\Socialite\\' => array($vendorDir . '/overtrue/socialite/src'),
'Overtrue\\Pinyin\\' => array($vendorDir . '/overtrue/pinyin/src'),
'OSS\\' => array($vendorDir . '/aliyuncs/oss-sdk-php/src/OSS'),
'MyCLabs\\Enum\\' => array($vendorDir . '/myclabs/php-enum/src'),
'Monolog\\' => array($vendorDir . '/monolog/monolog/src/Monolog'),

View File

@ -113,6 +113,7 @@ class ComposerStaticInit89c8a151cf27b567cd0b0fc6ee27341c
'O' =>
array (
'Overtrue\\Socialite\\' => 19,
'Overtrue\\Pinyin\\' => 16,
'OSS\\' => 4,
),
'M' =>
@ -361,6 +362,10 @@ class ComposerStaticInit89c8a151cf27b567cd0b0fc6ee27341c
array (
0 => __DIR__ . '/..' . '/overtrue/socialite/src',
),
'Overtrue\\Pinyin\\' =>
array (
0 => __DIR__ . '/..' . '/overtrue/pinyin/src',
),
'OSS\\' =>
array (
0 => __DIR__ . '/..' . '/aliyuncs/oss-sdk-php/src/OSS',

View File

@ -2150,6 +2150,68 @@
},
"install-path": "../open-smf/connection-pool"
},
{
"name": "overtrue/pinyin",
"version": "5.2.2",
"version_normalized": "5.2.2.0",
"dist": {
"type": "zip",
"url": "https://mirrors.tencent.com/repository/composer/overtrue/pinyin/5.2.2/overtrue-pinyin-5.2.2.zip",
"reference": "1cb6fdfe0c90d1895bb2f877a33ab2c0b58cb21c",
"shasum": ""
},
"require": {
"php": ">=8.0.2"
},
"require-dev": {
"brainmaestro/composer-git-hooks": "^2.7",
"friendsofphp/php-cs-fixer": "^3.2",
"laravel/pint": "^1.10",
"nunomaduro/termwind": "^1.13",
"phpunit/phpunit": "^10.1"
},
"time": "2023-09-27T08:07:28+00:00",
"bin": [
"bin/pinyin"
],
"type": "library",
"extra": {
"hooks": {
"pre-commit": [
"composer pint",
"composer test"
],
"pre-push": [
"composer pint",
"composer test"
]
}
},
"installation-source": "dist",
"autoload": {
"psr-4": {
"Overtrue\\Pinyin\\": "src/"
}
},
"license": [
"MIT"
],
"authors": [
{
"name": "overtrue",
"email": "anzhengchao@gmail.com",
"homepage": "http://github.com/overtrue"
}
],
"description": "Chinese to pinyin translator.",
"homepage": "https://github.com/overtrue/pinyin",
"keywords": [
"Chinese",
"Pinyin",
"cn2pinyin"
],
"install-path": "../overtrue/pinyin"
},
{
"name": "overtrue/socialite",
"version": "2.0.23",

View File

@ -3,7 +3,7 @@
'name' => 'topthink/think',
'pretty_version' => 'dev-master',
'version' => 'dev-master',
'reference' => '7e2f3cc9098f8c92a961355ce2253545ea1caba0',
'reference' => 'fc327528150855d45f95c1d0fbda6a1850984299',
'type' => 'project',
'install_path' => __DIR__ . '/../../',
'aliases' => array(),
@ -298,6 +298,15 @@
'aliases' => array(),
'dev_requirement' => false,
),
'overtrue/pinyin' => array(
'pretty_version' => '5.2.2',
'version' => '5.2.2.0',
'reference' => '1cb6fdfe0c90d1895bb2f877a33ab2c0b58cb21c',
'type' => 'library',
'install_path' => __DIR__ . '/../overtrue/pinyin',
'aliases' => array(),
'dev_requirement' => false,
),
'overtrue/socialite' => array(
'pretty_version' => '2.0.23',
'version' => '2.0.23.0',
@ -703,7 +712,7 @@
'topthink/think' => array(
'pretty_version' => 'dev-master',
'version' => 'dev-master',
'reference' => '7e2f3cc9098f8c92a961355ce2253545ea1caba0',
'reference' => 'fc327528150855d45f95c1d0fbda6a1850984299',
'type' => 'project',
'install_path' => __DIR__ . '/../../',
'aliases' => array(),

View File

@ -4,8 +4,8 @@
$issues = array();
if (!(PHP_VERSION_ID >= 70200)) {
$issues[] = 'Your Composer dependencies require a PHP version ">= 7.2.0". You are running ' . PHP_VERSION . '.';
if (!(PHP_VERSION_ID >= 80002)) {
$issues[] = 'Your Composer dependencies require a PHP version ">= 8.0.2". You are running ' . PHP_VERSION . '.';
}
if ($issues) {

View File

@ -0,0 +1 @@
github: [overtrue]

View File

@ -0,0 +1,12 @@
version: 2
updates:
- package-ecosystem: composer
directory: "/"
schedule:
interval: daily
time: "21:00"
open-pull-requests-limit: 10
ignore:
- dependency-name: phpunit/phpunit
versions:
- ">= 8.a, < 9"

View File

@ -0,0 +1,22 @@
name: Test
on: [push, pull_request]
jobs:
phpunit:
name: PHP-${{ matrix.php_version }}-${{ matrix.perfer }}
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
php_version:
- 8.0
- 8.1
perfer:
- stable
- lowest
steps:
- uses: actions/checkout@master
- name: Install Dependencies
run: composer update --prefer-dist --no-interaction --no-suggest --prefer-${{ matrix.perfer }}
- name: Run PHPUnit
run: ./vendor/bin/phpunit

21
server/vendor/overtrue/pinyin/LICENSE vendored Normal file
View File

@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2014 安正超
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

272
server/vendor/overtrue/pinyin/README.md vendored Normal file
View File

@ -0,0 +1,272 @@
# Pinyin
[![Test](https://github.com/overtrue/pinyin/actions/workflows/test.yml/badge.svg)](https://github.com/overtrue/pinyin/actions/workflows/test.yml)
[![Latest Stable Version](https://poser.pugx.org/overtrue/pinyin/v/stable.svg)](https://packagist.org/packages/overtrue/pinyin) [![Total Downloads](https://poser.pugx.org/overtrue/pinyin/downloads.svg)](https://packagist.org/packages/overtrue/pinyin) [![Latest Unstable Version](https://poser.pugx.org/overtrue/pinyin/v/unstable.svg)](https://packagist.org/packages/overtrue/pinyin) [![License](https://poser.pugx.org/overtrue/pinyin/license.svg)](https://packagist.org/packages/overtrue/pinyin)
:cn: 基于 [mozillazg/pinyin-data](https://github.com/mozillazg/pinyin-data) 词典的中文转拼音工具,更准确的支持多音字的汉字转拼音解决方案。
[喜欢我的项目?点击这里支持我](https://github.com/sponsors/overtrue)
## 安装
使用 Composer 安装:
```bash
composer require overtrue/pinyin:^5.0
```
## 使用
### 拼音风格
除了获取首字母的方法外,所有方法都支持第二个参数,用于指定拼音的格式,可选值为:
- `symbol` (默认)声调符号,例如 `pīn yīn`
- `none` 不输出拼音,例如 `pin yin`
- `number` 末尾数字模式的拼音,例如 `pin1 yin1`
### 返回值
除了 `permalink` 返回字符串外,其它方法都返回集合类型 [`Overtrue\Pinyin\Collection`](https://github.com/overtrue/pinyin/blob/master/src/Collection.php)
```php
use Overtrue\Pinyin\Pinyin;
$pinyin = Pinyin::sentence('你好,世界');
```
你可以通过以下方式访问集合内容:
```php
echo $pinyin; // nǐ hǎo shì jiè
// 直接将对象转成字符串
$string = (string) $pinyin; // nǐ hǎo shì jiè
$pinyin->toArray(); // ['nǐ', 'hǎo', 'shì', 'jiè']
// 直接使用索引访问
$pinyin[0]; // 'nǐ'
// 使用函数遍历
$pinyin->map('ucfirst'); // ['Nǐ', 'Hǎo', 'Shì', 'Jiè']
// 拼接为字符串
$pinyin->join(' '); // 'nǐ hǎo shì jiè'
$pinyin->join('-'); // 'nǐ-hǎo-shì-jiè'
// 转成 json
$pinyin->toJson(); // '["nǐ","hǎo","shì","jiè"]'
json_encode($pinyin); // '["nǐ","hǎo","shì","jiè"]'
```
### 文字段落转拼音
```php
use Overtrue\Pinyin\Pinyin;
echo Pinyin::sentence('带着希望去旅行,比到达终点更美好');
// dài zhe xī wàng qù lǚ xíng bǐ dào dá zhōng diǎn gèng měi hǎo
// 去除声调
echo Pinyin::sentence('带着希望去旅行,比到达终点更美好', 'none');
// dai zhe xi wang qu lv xing bi dao da zhong dian geng mei hao
```
### 生成用于链接的拼音字符串
通常用于文章链接等,可以使用 `permalink` 方法获取拼音字符串:
```php
echo Pinyin::permalink('带着希望去旅行'); // dai-zhe-xi-wang-qu-lyu-xing
echo Pinyin::permalink('带着希望去旅行', '.'); // dai.zhe.xi.wang.qu.lyu.xing
```
### 获取首字符字符串
通常用于创建搜索用的索引,可以使用 `abbr` 方法转换:
```php
Pinyin::abbr('带着希望去旅行'); // ['d', 'z', 'x', 'w', 'q', 'l', 'x']
echo Pinyin::abbr('带着希望去旅行')->join('-'); // d-z-x-w-q-l-x
echo Pinyin::abbr('你好2018')->join(''); // nh2018
echo Pinyin::abbr('Happy New Year! 2018')->join(''); // HNY2018
```
**姓名首字母**
将首字作为姓氏转换,其余作为普通词语转换:
```php
Pinyin::nameAbbr('欧阳'); // ['o', 'y']
echo Pinyin::nameAbbr('单单单')->join('-'); // s-d-d
```
### 姓名转换
姓名的姓的读音有些与普通字不一样,比如 ‘单’ 常见的音为 `dan`,而作为姓的时候读 `shan`
```php
Pinyin::name('单某某'); // ['shàn', 'mǒu', 'mǒu']
Pinyin::name('单某某', 'none'); // ['shan', 'mou', 'mou']
Pinyin::name('单某某', 'none')->join('-'); // shan-mou-mou
```
### 护照姓名转换
根据国家规定 [关于中国护照旅行证上姓名拼音 ü(吕、律、闾、绿、女等)统一拼写为 YU 的提醒](http://sg.china-embassy.gov.cn/lsfw/zghz1/hzzxdt/201501/t20150122_2022198.htm) 的规则,将 `ü` 转换为 `yu`
```php
Pinyin::passportName('吕小布'); // ['lyu', 'xiao', 'bu']
Pinyin::passportName('女小花'); // ['nyu', 'xiao', 'hua']
Pinyin::passportName('律师'); // ['lyu', 'shi']
```
### 多音字
多音字的返回值为关联数组的集合,默认返回去重后的所有读音:
```php
$pinyin = Pinyin::polyphones('重庆');
$pinyin['重']; // ["zhòng", "chóng", "tóng"]
$pinyin['庆']; // ["qìng"]
$pinyin->toArray();
// [
// "重": ["zhòng", "chóng", "tóng"],
// "庆": ["qìng"]
// ]
```
如果不想要去重,可以数组形式返回:
```php
$pinyin = Pinyin::polyphones('重庆重庆', Converter::TONE_STYLE_SYMBOL, true);
// or
$pinyin = Pinyin::polyphonesAsArray('重庆重庆', Converter::TONE_STYLE_SYMBOL);
$pinyin->toArray();
// [
// ["重" => ["zhòng", "chóng", "tóng"]],
// ["庆" => ["qìng"]],
// ["重" => ["zhòng", "chóng", "tóng"]],
// ["庆" => ["qìng"]]
// ]
```
### 单字转拼音
和多音字类似,单字的返回值为字符串,多音字将根据该字字频调整得到常用音:
```php
$pinyin = Pinyin::chars('重庆');
echo $pinyin['重']; // "zhòng"
echo $pinyin['庆']; // "qìng"
$pinyin->toArray();
// [
// "重": "zhòng",
// "庆": "qìng"
// ]
```
> **Warning**
>
> 当单字处理时由于多音字来自词频表中取得常用音,所以在词语环境下可能出现不正确的情况,建议使用多音字处理。
更多使用请参考 [测试用例](https://github.com/overtrue/pinyin/blob/master/tests/PinyinTest.php)。
## v/yu/ü 的问题
根据国家语言文字工作委员会的规定,`lv`、`lyu`、`lǚ` 都是正确的,但是 `lv` 是最常用的,所以默认使用 `lv`,如果你需要使用其他的,可以在初始化时传入:
```php
echo Pinyin::sentence('旅行');
// lǚ xíng
echo Pinyin::sentence('旅行', 'none');
// lv xing
echo Pinyin::yuToYu()->sentence('旅行', 'none');
// lyu xing
echo Pinyin::yuToU()->sentence('旅行', 'none');
// lu xing
echo Pinyin::yuToV()->sentence('旅行', 'none');
// lv xing
```
> **Warning**
>
> 仅在拼音风格为非 `none` 模式下有效。
## 命令行工具
你可以使用命令行来实现拼音的转换:
```bash
php ./bin/pinyin 带着希望去旅行 --method=sentence --tone-style=symbol
# dài zhe xī wàng qù lǚ xíng
```
更多使用方法,可以查看帮助文档:
```bash
php ./bin/pinyin --help
# Usage:
# ./pinyin [chinese] [method] [options]
# Options:
# -j, --json 输出 JSON 格式.
# -c, --compact 不格式化输出 JSON.
# -m, --method=[method] 转换方式可选sentence/permalink/abbr/nameAbbr/name/passportName/phrase/polyphones/chars.
# --no-tone 不使用音调.
# --tone-style=[style] 音调风格可选值symbol/none/number, default: none.
# -h, --help 显示帮助.
```
## 在 Laravel 中使用
独立的包在这里:[overtrue/laravel-pinyin](https://github.com/overtrue/laravel-pinyin)
## 中文简繁转换
如何你有这个需求,也可以了解我的另一个包:[overtrue/php-opencc](https://github.com/overtrue/php-opencc)
## Contribution
欢迎提意见及完善补充词库:
- 单字拼音错误请添加到:[sources/pathes/chars.txt](https://github.com/overtrue/pinyin/blob/master/sources/pathes/chars.txt)
- 词语错误或补齐,请添加到:[sources/pathes/words.txt](https://github.com/overtrue/pinyin/blob/master/sources/pathes/words.txt)
## 参考
- [mozillazg/pinyin-data](https://github.com/mozillazg/pinyin-data)
- [详细参考资料](https://github.com/overtrue/pinyin-resources)
## :heart: Sponsor me
[![Sponsor me](https://github.com/overtrue/overtrue/blob/master/sponsor-me.svg?raw=true)](https://github.com/sponsors/overtrue)
如果你喜欢我的项目并想支持它,[点击这里 :heart:](https://github.com/sponsors/overtrue)
## Project supported by JetBrains
Many thanks to Jetbrains for kindly providing a license for me to work on this and other open-source projects.
[![](https://resources.jetbrains.com/storage/products/company/brand/logos/jb_beam.svg)](https://www.jetbrains.com/?from=https://github.com/overtrue)
## PHP 扩展包开发
> 想知道如何从零开始构建 PHP 扩展包?
>
> 请关注我的实战课程,我会在此课程中分享一些扩展开发经验 —— [《PHP 扩展包实战教程 - 从入门到发布》](https://learnku.com/courses/creating-package)
# License
MIT

View File

@ -0,0 +1,84 @@
#!/usr/bin/env php
<?php
require __DIR__ . '/../vendor/autoload.php';
use Overtrue\Pinyin\Pinyin;
$input = $argv[1] ?? null;
$methods = explode(',', 'name,phrase,permalink,polyphones,chars,nameAbbr,abbr,sentence');
$method = 'sentence';
$inputOptions = [];
$help = <<<"HELP"
Usage:
./pinyin [chinese] [method] [options]
Options:
-j, --json 输出 JSON 格式.
-c, --compact 不格式化输出 JSON.
-m, --method=[method] 转换方式可选sentence/permalink/abbr/nameAbbr/name/passportName/phrase/polyphones/chars.
--no-tone 不使用音调.
--tone-style=[style] 音调风格可选值symbol/none/number, default: none.
-h, --help 显示帮助.
HELP;
foreach ($argv as $i => $arg) {
if ($i === 0) {
continue;
}
if (in_array($arg, $methods)) {
$method = $arg;
} elseif (str_starts_with($arg, '-')) {
[$key, $value] = array_pad(array_map('trim', explode('=', $arg, 2)), 2, null);
$inputOptions[$key] = $value;
}
}
function has_option($option, $alias = null): bool
{
global $inputOptions;
if ($alias) {
return array_key_exists($option, $inputOptions) || array_key_exists($alias, $inputOptions);
}
return array_key_exists($option, $inputOptions);
}
function get_option($option, $default = null, $alias = null): ?string
{
global $inputOptions;
if ($alias) {
return $inputOptions[$option] ?? $inputOptions[$alias] ?? $default;
}
return $inputOptions[$option] ?? $default;
}
if (empty($input) || has_option('--help', '-h')) {
echo $help;
exit(0);
}
if (has_option('--method', '-m')) {
$method = get_option('--method');
}
$toneStyle = has_option('--no-tone') ? 'none' : get_option('--tone-style', 'none');
$result = Pinyin::$method($input, $method === 'permalink' ? '-' : $toneStyle);
$toJson = has_option('--json', '-j') || in_array($method, ['polyphones']);
if ($toJson) {
$options = JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT;
if (has_option('--compact', '-c')) {
$options = 0;
}
$result = json_encode($result, $options);
}
echo $result, "\n";

View File

@ -0,0 +1,70 @@
{
"name": "overtrue/pinyin",
"description": "Chinese to pinyin translator.",
"keywords": [
"chinese",
"pinyin",
"cn2pinyin"
],
"homepage": "https://github.com/overtrue/pinyin",
"license": "MIT",
"authors": [
{
"name": "overtrue",
"homepage": "http://github.com/overtrue",
"email": "anzhengchao@gmail.com"
}
],
"autoload": {
"psr-4": {
"Overtrue\\Pinyin\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"Overtrue\\Pinyin\\Tests\\": "tests/"
}
},
"require": {
"php": ">=8.0.2"
},
"require-dev": {
"phpunit/phpunit": "^10.1",
"brainmaestro/composer-git-hooks": "^2.7",
"friendsofphp/php-cs-fixer": "^3.2",
"nunomaduro/termwind": "^1.13",
"laravel/pint": "^1.10"
},
"bin": ["bin/pinyin"],
"extra": {
"hooks": {
"pre-commit": [
"composer pint",
"composer test"
],
"pre-push": [
"composer pint",
"composer test"
]
}
},
"scripts": {
"post-update-cmd": [
"cghooks update"
],
"post-merge": "composer install",
"post-install-cmd": [
"cghooks remove",
"cghooks add --ignore-lock"
],
"cghooks": "vendor/bin/cghooks",
"pint": "vendor/bin/pint ./src ./tests",
"fix-style": "vendor/bin/pint ./src ./tests",
"test": "vendor/bin/phpunit --colors=always",
"build": "php ./bin/build"
},
"scripts-descriptions": {
"test": "Run all tests.",
"fix-style": "Run style checks and fix violations."
}
}

177507
server/vendor/overtrue/pinyin/data/chars.php vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,86 @@
<?php
return array (
'万俟' => ' mò qí ',
'尉迟' => ' yù chí ',
'单于' => ' chán yú ',
'重' => ' chóng ',
'秘' => ' bì ',
'冼' => ' xiǎn ',
'华' => ' huà ',
'过' => ' guō ',
'纪' => ' jǐ ',
'燕' => ' yān ',
'种' => ' chóng ',
'繁' => ' pó ',
'幺' => ' yāo ',
'覃' => ' qín ',
'冯' => ' féng ',
'石' => ' shí ',
'缪' => ' miào ',
'瞿' => ' qú ',
'曾' => ' zēng ',
'解' => ' xiè ',
'折' => ' shè ',
'那' => ' nā ',
'佴' => ' nài ',
'难' => ' nàn ',
'粘' => ' niàn ',
'藏' => ' zàng ',
'扎' => ' zā ',
'翟' => ' zhái ',
'都' => ' dū ',
'六' => ' lù ',
'薄' => ' bó ',
'贾' => ' jiǎ ',
'的' => ' dē ',
'哈' => ' hǎ ',
'居' => ' jū ',
'盖' => ' gě ',
'查' => ' zhā ',
'盛' => ' shèng ',
'塔' => ' tǎ ',
'和' => ' hé ',
'柏' => ' bǎi ',
'朴' => ' piáo ',
'蓝' => ' lán ',
'牟' => ' móu ',
'殷' => ' yīn ',
'陆' => ' lù ',
'乜' => ' niè ',
'乐' => ' yuè ',
'阚' => ' kàn ',
'叶' => ' yè ',
'强' => ' qiáng ',
'不' => ' fǒu ',
'丁' => ' dīng ',
'阿' => ' ā ',
'汤' => ' tāng ',
'万' => ' wàn ',
'车' => ' chē ',
'称' => ' chēng ',
'沈' => ' shěn ',
'区' => ' ōu ',
'仇' => ' qiú ',
'宿' => ' sù ',
'南' => ' nán ',
'单' => ' shàn ',
'卜' => ' bǔ ',
'鸟' => ' niǎo ',
'思' => ' sī ',
'殳' => ' shū ',
'寻' => ' xún ',
'於' => ' yú ',
'烟' => ' yān ',
'余' => ' yú ',
'浅' => ' qiǎn ',
'艾' => ' ài ',
'浣' => ' wǎn ',
'无' => ' wú ',
'信' => ' xìn ',
'许' => ' xǔ ',
'齐' => ' qí ',
'俞' => ' yú ',
'若' => ' ruò ',
'贠' => ' yùn ',
'貟' => ' yùn ',
);

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,6 @@
parameters:
level: 9
paths:
- src
inferPrivatePropertyTypeFromConstructor: true
checkMissingIterableValueType: false

View File

@ -0,0 +1,75 @@
<?php
namespace Overtrue\Pinyin;
use ArrayAccess;
use JsonSerializable;
use Stringable;
class Collection implements ArrayAccess, JsonSerializable, Stringable
{
public function __construct(protected $items = [])
{
}
public function join(string $separator = ' '): string
{
return implode($separator, \array_map(function ($item) {
return \is_array($item) ? '['.\implode(', ', $item).']' : $item;
}, $this->items));
}
public function map(callable $callback): Collection
{
return new static(array_map($callback, $this->all()));
}
public function all(): array
{
return $this->items;
}
public function toArray(): array
{
return $this->all();
}
public function toJson(int $options = 0): string
{
return json_encode($this->all(), $options);
}
public function __toString()
{
return $this->join();
}
public function offsetExists(mixed $offset): bool
{
return isset($this->items[$offset]);
}
public function offsetGet(mixed $offset): mixed
{
return $this->items[$offset] ?? null;
}
public function offsetSet(mixed $offset, mixed $value): void
{
if (null === $offset) {
$this->items[] = $value;
} else {
$this->items[$offset] = $value;
}
}
public function offsetUnset(mixed $offset): void
{
unset($this->items[$offset]);
}
public function jsonSerialize(): mixed
{
return $this->items;
}
}

View File

@ -0,0 +1,278 @@
<?php
namespace Overtrue\Pinyin;
class Converter
{
private const SEGMENTS_COUNT = 10;
private const WORDS_PATH = __DIR__.'/../data/words-%s.php';
private const CHARS_PATH = __DIR__.'/../data/chars.php';
private const SURNAMES_PATH = __DIR__.'/../data/surnames.php';
public const TONE_STYLE_SYMBOL = 'symbol';
public const TONE_STYLE_NUMBER = 'number';
public const TONE_STYLE_NONE = 'none';
protected bool $polyphonic = false;
protected bool $polyphonicAsList = false;
protected bool $asSurname = false;
protected bool $noWords = false;
protected string $yuTo = 'v';
protected string $toneStyle = self::TONE_STYLE_SYMBOL;
protected array $regexps = [
'separator' => '\p{Z}',
'mark' => '\p{M}',
'tab' => "\t",
];
public const REGEXPS = [
'number' => '0-9',
'alphabet' => 'a-zA-Z',
// 中文不带符号
'hans' => '\x{3007}\x{2E80}-\x{2FFF}\x{3100}-\x{312F}\x{31A0}-\x{31EF}\x{3400}-\x{4DBF}\x{4E00}-\x{9FFF}\x{F900}-\x{FAFF}',
// 符号: !"#$%&'()*+,-./:;<=>?@[\]^_{|}~`
'punctuation' => '\p{P}',
];
public function __construct()
{
$this->regexps = \array_merge($this->regexps, self::REGEXPS);
}
public static function make(): static
{
return new static();
}
public function polyphonic(bool $asList = false): static
{
$this->polyphonic = true;
$this->polyphonicAsList = $asList;
return $this;
}
public function surname(): static
{
$this->asSurname = true;
return $this;
}
public function noWords(): static
{
$this->noWords = true;
return $this;
}
public function onlyHans(): static
{
// 中文汉字不含符号
$this->regexps['hans'] = self::REGEXPS['hans'];
return $this->noAlpha()->noNumber()->noPunctuation();
}
public function noAlpha(): static
{
unset($this->regexps['alphabet']);
return $this;
}
public function noNumber(): static
{
unset($this->regexps['number']);
return $this;
}
public function noPunctuation(): static
{
unset($this->regexps['punctuation']);
return $this;
}
public function withToneStyle(string $toneStyle): static
{
$this->toneStyle = $toneStyle;
return $this;
}
public function noTone(): static
{
$this->toneStyle = self::TONE_STYLE_NONE;
return $this;
}
public function useNumberTone(): static
{
$this->toneStyle = self::TONE_STYLE_NUMBER;
return $this;
}
public function yuToYu(): static
{
$this->yuTo = 'yu';
return $this;
}
public function yuToV(): static
{
$this->yuTo = 'v';
return $this;
}
public function yuToU(): static
{
$this->yuTo = 'u';
return $this;
}
public function when(bool $condition, callable $callback): static
{
if ($condition) {
$callback($this);
}
return $this;
}
public function convert(string $string, callable $beforeSplit = null): Collection
{
// 把原有的数字和汉字分离,避免拼音转换时被误作声调
$string = preg_replace_callback('~[a-z0-9_-]+~i', function ($matches) {
return "\t".$matches[0];
}, $string);
// 过滤掉不保留的字符
$string = \preg_replace(\sprintf('~[^%s]~u', \implode($this->regexps)), '', $string);
// 多音字
if ($this->polyphonic) {
return $this->convertAsChars($string, true);
}
if ($this->noWords) {
return $this->convertAsChars($string);
}
// 替换姓氏
if ($this->asSurname) {
$string = $this->convertSurname($string);
}
for ($i = 0; $i < self::SEGMENTS_COUNT; $i++) {
$string = strtr($string, require sprintf(self::WORDS_PATH, $i));
}
return $this->split($beforeSplit ? $beforeSplit($string) : $string);
}
public function convertAsChars(string $string, bool $polyphonic = false): Collection
{
$map = require self::CHARS_PATH;
// split string as chinese chars
$chars = preg_split('//u', $string, -1, PREG_SPLIT_NO_EMPTY);
$items = [];
foreach ($chars as $char) {
if (isset($map[$char])) {
if ($polyphonic) {
$pinyin = \array_map(fn ($pinyin) => $this->formatTone($pinyin, $this->toneStyle), $map[$char]);
if ($this->polyphonicAsList) {
$items[] = [$char => $pinyin];
} else {
$items[$char] = $pinyin;
}
} else {
$items[$char] = $this->formatTone($map[$char][0], $this->toneStyle);
}
}
}
return new Collection($items);
}
protected function convertSurname(string $name): string
{
static $surnames = null;
$surnames ??= require self::SURNAMES_PATH;
foreach ($surnames as $surname => $pinyin) {
if (\str_starts_with($name, $surname)) {
return $pinyin.\mb_substr($name, \mb_strlen($surname));
}
}
return $name;
}
protected function split(string $item): Collection
{
$items = \array_values(array_filter(preg_split('/\s+/i', $item)));
foreach ($items as $index => $item) {
$items[$index] = $this->formatTone($item, $this->toneStyle);
}
return new Collection($items);
}
protected function formatTone(string $pinyin, string $style): string
{
if ($style === self::TONE_STYLE_SYMBOL) {
return $pinyin;
}
$replacements = [
// mb_chr(593) => 'ɑ' 轻声中除了 `ɑ` 和 `ü` 以外,其它和字母一样
'ɑ' => ['a', 5], 'ü' => ['v', 5],
'üē' => ['ue', 1], 'üé' => ['ue', 2], 'üě' => ['ue', 3], 'üè' => ['ue', 4],
'ā' => ['a', 1], 'ē' => ['e', 1], 'ī' => ['i', 1], 'ō' => ['o', 1], 'ū' => ['u', 1], 'ǖ' => ['v', 1],
'á' => ['a', 2], 'é' => ['e', 2], 'í' => ['i', 2], 'ó' => ['o', 2], 'ú' => ['u', 2], 'ǘ' => ['v', 2],
'ǎ' => ['a', 3], 'ě' => ['e', 3], 'ǐ' => ['i', 3], 'ǒ' => ['o', 3], 'ǔ' => ['u', 3], 'ǚ' => ['v', 3],
'à' => ['a', 4], 'è' => ['e', 4], 'ì' => ['i', 4], 'ò' => ['o', 4], 'ù' => ['u', 4], 'ǜ' => ['v', 4],
];
foreach ($replacements as $unicode => $replacement) {
if (\str_contains($pinyin, $unicode)) {
$umlaut = $replacement[0];
// https://zh.wikipedia.org/wiki/%C3%9C
if ($this->yuTo !== 'v' && $umlaut === 'v') {
$umlaut = $this->yuTo;
}
$pinyin = \str_replace($unicode, $umlaut, $pinyin);
if ($this->toneStyle === self::TONE_STYLE_NUMBER) {
$pinyin .= $replacement[1];
}
}
}
return $pinyin;
}
}

View File

@ -0,0 +1,95 @@
<?php
namespace Overtrue\Pinyin;
use InvalidArgumentException;
/**
* @method static Converter surname()
* @method static Converter noWords()
* @method static Converter onlyHans()
* @method static Converter noAlpha()
* @method static Converter noNumber()
* @method static Converter noPunctuation()
* @method static Converter noTone()
* @method static Converter useNumberTone()
* @method static Converter yuToV()
* @method static Converter yuToU()
* @method static Converter polyphonic(bool $asList = false)
* @method static Converter withToneStyle(string $toneStyle = 'symbol')
* @method static Collection convert(string $string, callable $beforeSplit = null)
*/
class Pinyin
{
public static function name(string $name, string $toneStyle = Converter::TONE_STYLE_SYMBOL): Collection
{
return self::surname()->withToneStyle($toneStyle)->convert($name);
}
public static function passportName(string $name, string $toneStyle = Converter::TONE_STYLE_NONE): Collection
{
return self::surname()->yuToYu()->withToneStyle($toneStyle)->convert($name);
}
public static function phrase(string $string, string $toneStyle = Converter::TONE_STYLE_SYMBOL): Collection
{
return self::noPunctuation()->withToneStyle($toneStyle)->convert($string);
}
public static function sentence(string $string, string $toneStyle = Converter::TONE_STYLE_SYMBOL): Collection
{
return self::withToneStyle($toneStyle)->convert($string);
}
public static function polyphones(string $string, string $toneStyle = Converter::TONE_STYLE_SYMBOL, bool $asList = false): Collection
{
return self::polyphonic($asList)->withToneStyle($toneStyle)->convert($string);
}
public static function polyphonesAsArray(string $string, string $toneStyle = Converter::TONE_STYLE_SYMBOL): Collection
{
return self::polyphones($string, $toneStyle, true);
}
public static function chars(string $string, string $toneStyle = Converter::TONE_STYLE_SYMBOL): Collection
{
return self::onlyHans()->noWords()->withToneStyle($toneStyle)->convert($string);
}
public static function permalink(string $string, string $delimiter = '-'): string
{
if (! in_array($delimiter, ['_', '-', '.', ''], true)) {
throw new InvalidArgumentException("Delimiter must be one of: '_', '-', '', '.'.");
}
return self::noPunctuation()->noTone()->convert($string)->join($delimiter);
}
public static function nameAbbr(string $string): Collection
{
return self::abbr($string, true);
}
public static function abbr(string $string, bool $asName = false): Collection
{
return self::noTone()
->noPunctuation()
->when($asName, fn ($c) => $c->surname())
->convert($string)
->map(function ($pinyin) {
// 常用于电影名称入库索引处理例如《晚娘2012》-> WN2012
return \is_numeric($pinyin) || preg_match('/\d{2,}/', $pinyin) ? $pinyin : \mb_substr($pinyin, 0, 1);
});
}
public static function __callStatic(string $name, array $arguments)
{
$converter = Converter::make();
if (\method_exists($converter, $name)) {
return $converter->$name(...$arguments);
}
throw new InvalidArgumentException("Method {$name} does not exist.");
}
}

View File

@ -1,5 +1,5 @@
<?php
// This file is automatically generated at:2023-09-28 14:28:35
// This file is automatically generated at:2023-10-12 15:48:08
declare (strict_types = 1);
return array (
0 => 'think\\captcha\\CaptchaService',