gettext / languages
具有复数规则的 gettext 语言
Requires
- php: >=5.3
Requires (Dev)
- phpunit/phpunit: ^4.8 || ^5.7 || ^6.5 || ^7.5 || ^8.4
README
gettext 语言列表自动从 CLDR 数据生成
静态使用
要使用此工具生成的语言数据,可以使用 bin/export-plural-rules
命令。
导出命令行选项
export-plural-rules
支持以下选项
--us-ascii
如果指定,输出将仅包含 US-ASCII 字符。如果没有指定,输出字符集为 UTF-8。--languages=<LanguageId>[,<LanguageId>,...]]
--language=<LanguageId>[,<LanguageId>,...]]
仅导出指定的语言代码。用逗号分隔语言;您也可以多次使用此参数;它不区分大小写,并接受 '_' 和 '-' 作为区域设置块分隔符(例如,我们接受it_IT
以及it-it
)。如果没有指定此选项,结果将包含所有可用语言。--reduce=yes|no
如果设置为 yes,输出将不会包含具有相同基本语言和规则的语言。例如,nl_BE
(佛兰芒语
)将被省略,因为它与nl
(荷兰语
)相同。如果指定了--languages
,则默认为no
,否则为yes
。--parenthesis=yes|no
如果设置为 no,生成的复数规则公式中将省略额外的括号。这些额外的括号需要创建与 PHP 兼容的公式。默认为yes
。--output=<file name>
如果指定,输出将保存到<file name>
。如果没有指定,我们将输出到标准输出。
导出格式
export-plural-rules
可以生成以下格式的数据
-
json
:压缩的 JSON 数据export-plural-rules json
-
prettyjson
:未压缩的 JSON 数据export-plural-rules prettyjson
-
html
:HTML 表格(查看结果)export-plural-rules html
-
php
:构建一个可以包含的 PHP 文件export-plural-rules --output=yourfile.php php
然后您可以在 PHP 脚本中使用该生成的文件
$languages = include 'yourfile.php';
-
ruby
:构建一个可以包含的 Ruby 文件export-plural-rules --parenthesis=no --output=yourfile.rb ruby
然后您可以在 Ruby 脚本中使用该生成的文件
require './yourfile.rb' PLURAL_RULES['en']
-
xml
:生成 XML 文档(此处可以找到 xsd XML 架构)export-plural-rules xml
-
po
:为单个语言生成 gettext .po 标头export-plural-rules po --language=YourLanguageCode
动态使用
使用 Composer
您可以使用 Composer 将此工具包含到您的项目中。只需运行 composer require gettext/languages
或将 "gettext/languages": "*"
添加到 composer.json
文件的 "require"
部分。
不使用 Composer
如果您在项目中不使用 composer,您可以将此包下载到项目的一个目录中,并包含自动加载文件
require_once 'path/to/src/autoloader.php';
主要方法
此工具最有用的函数如下
$allLanguages = Gettext\Languages\Language::getAll(); ... $oneLanguage = Gettext\Languages\Language::getById('en_US'); ...
getAll
返回一个 Gettext\Languages\Language
实例列表,getById
返回单个 Gettext\Languages\Language
实例(如果指定的语言标识符无效,则返回 null
)。
Gettext\Languages\Language
实例的主要属性包括
id
:规范化语言ID(例如en_US
)name
:语言名称(例如en_US
对应American English
)supersededBy
:替代此语言代码的语言代码(例如,jw
被替代为jv
以表示爪哇语)script
:脚本名称(例如,对于zh_Hans
-简体中文
- 脚本是简体汉字
)territory
:领土名称(例如en_US
对应United States
)baseLanguage
:基本语言名称(例如en_US
对应English
)formula
:用于区分不同复数规则的 gettext 公式。例如n != 1
categories
:适用于此语言的复数情况。它是一个包含Gettext\Languages\Category
实例的数组。每个实例具有以下属性id
:可以是以下顺序之一:zero
、one
、two
、few
、many
或other
。other
情况始终存在。examples
:表示此复数情况有效的某些值的表示(示例是简单的数字,如1
或复杂的范围,如0, 2~16, 100, 1000, 10000, 100000, 1000000, …
)
这些数据正确吗?
是 - 只要你信任 Unicode CLDR 项目。
从 CLDR 到 gettext 的转换还包括 大量测试 以检查结果。并且全部通过 😉。
参考
CLDR
CLDR 规范定义以下变量,用于在 CLDR 复数公式中引用
n
:源数字的绝对值(整数和小数)(例如:9.870
=>9.87
)i
:n 的整数位数(例如:9.870
=>9
)v
:n 中可见的小数位数,包括尾随零(例如:9.870
=>3
)w
:n 中可见的小数位数,不包括尾随零(例如:9.870
=>2
)f
:n 中的可见小数位数,包括尾随零(例如:9.870
=>870
)t
:n 中的可见小数位数,不包括尾随零(例如:9.870
=>87
)c
:用于紧凑十进制格式的10的幂的指数(例如:98c7
=>7
)e
:c
的同义词
gettext
gettext 规范定义以下变量,用于在 gettext 复数公式中使用
n
:无符号长整型
CLDR > gettext 转换
三元运算符中的括号
生成的 gettext 公式包含一些额外的括号,以避免某些编程语言中的问题。例如,假设我们有一个这样的公式:(0 == 0) ? 0 : (0 == 1) ? 1 : 2
- 在C中它评估为
0
,因为与(0 == 0) ? 0 : ((0 == 1) ? 1 : 2)
相同 - 在Java中它评估为
0
,因为与(0 == 0) ? 0 : ((0 == 1) ? 1 : 2)
相同 - 在JavaScript中它评估为
0
,因为与(0 == 0) ? 0 : ((0 == 1) ? 1 : 2)
相同 - 在PHP中它评估为
2
,因为与((0 == 0) ? 0 : (0 == 1)) ? 1 : 2
相同
为了避免问题,我们不是简单地使用 a ? 0 : b ? 1 : 2
,而是将结果公式格式化为这种形式:a ? 0 : (b ? 1 : 2)
贡献
生成 CLDR 数据
此仓库使用了 CLDR 数据,包括美国英语(en_US
)json 文件。为了生成这些数据,您可以使用 Docker。通过运行以下命令启动一个新的 Docker 容器:
docker run --rm -it -v path/to/src/cldr-data:/output alpine:3.13 sh
然后运行以下脚本,并根据您的需求设置变量的值
# The value of the CLDR version (eg 39, 38.1, ...) CLDR_VERSION=39 # Your GitHub username (required since CLDR 38) - see http://cldr.unicode.org/development/maven#TOC-Introduction GITHUB_USERNAME= # Your GitHub personal access token (required since CLDR 38) - see http://cldr.unicode.org/development/maven#TOC-Introduction GITHUB_TOKEN= if ! test -d /output; then echo 'Missing output directory' >&2 return 1 fi apk -U upgrade apk add --no-cache git git-lfs openjdk8 apache-ant maven CLDR_MAJORVERSION="$(printf '%s' "$CLDR_VERSION" | sed -E 's/^([0-9]+).*/\1/')" SOURCE_DIR="$(mktemp -d)" DESTINATION_DIR="$(mktemp -d)" git clone --single-branch --depth=1 "--branch=release-$(printf '%s' "$CLDR_VERSION" | tr '.' '-')" https://github.com/unicode-org/cldr.git "$SOURCE_DIR" if test $CLDR_MAJORVERSION -lt 38; then git -C "$SOURCE_DIR" lfs pull --include tools/java || true ant -f "$SOURCE_DIR/tools/java/build.xml" jar JARFILE="$SOURCE_DIR/tools/java/cldr.jar" DESTINATION_DIR_LOCALE="$DESTINATION_DIR/en_US" DESTINATION_FILE_PLURALS="$DESTINATION_DIR/supplemental/plurals.json" else if test -z "${GITHUB_USERNAME:-}"; then echo 'GITHUB_USERNAME is missing' >&2 return 1 fi if test -z "${GITHUB_TOKEN:-}"; then echo 'GITHUB_TOKEN is missing' >&2 return 1 fi printf '<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"><servers><server><id>githubicu</id><username>%s</username><password>%s</password></server></servers></settings>' "$GITHUB_USERNAME" "$GITHUB_TOKEN" > "$SOURCE_DIR/mvn-settings.xml" mvn --settings "$SOURCE_DIR/mvn-settings.xml" package -DskipTests=true --file "$SOURCE_DIR/tools/cldr-code/pom.xml" JARFILE="$SOURCE_DIR//tools/cldr-code/target/cldr-code.jar" DESTINATION_DIR_LOCALE="$DESTINATION_DIR" DESTINATION_FILE_PLURALS="$DESTINATION_DIR/supplemental/plurals/plurals.json" fi java -Duser.language=en -Duser.country=US "-DCLDR_DIR=$SOURCE_DIR" "-DCLDR_GEN_DIR=$DESTINATION_DIR_LOCALE" -jar "$JARFILE" ldml2json -t main -r true -s contributed -m en_US java -Duser.language=en -Duser.country=US "-DCLDR_DIR=$SOURCE_DIR" "-DCLDR_GEN_DIR=$DESTINATION_DIR/supplemental" -jar "$JARFILE" ldml2json -s contributed -o true -t supplemental mkdir -p /output/main/en-US cp $DESTINATION_DIR/en_US/languages.json /output/main/en-US/ cp $DESTINATION_DIR/en_US/scripts.json /output/main/en-US/ cp $DESTINATION_DIR/en_US/territories.json /output/main/en-US/ mkdir -p /output/supplemental cp "$DESTINATION_FILE_PLURALS" /output/supplemental/