162 files and 67,501 messages per language; 324 files and 135,002 messages in total. Both languages are 100% translated, with zero fuzzy and zero untranslated entries — every file clean under msgfmt --check --check-format.
The initial zh_CN baseline from pgtranslation/messages.git dated from 2019; its headers still read Project-Id-Version: postgres (PostgreSQL) 12. Across PostgreSQL 14 – 19 it carried a reviewed translation for 77.1% of messages; of the remaining 15,475, some 11,770 were fuzzy entries that babel matched by similarity and 3,705 were empty. This repository is a complete set rebuilt from the current templates, with terminology held to a single glossary shared across all catalogs and all six branches, and every message verified against its English original. How that was done is spelled out in How this was made.
Every message is browsable at https://pgsql.cc/nls — the English original, the existing translation and the calibrated translation side by side, filterable by catalog, full-text searchable, with the real provenance of similar wordings. Corrections and second opinions are welcome there.
| Upstream branch | PG | Catalogs | Messages | Initial upstream | Here | Workbench | Issue | Download |
|---|---|---|---|---|---|---|---|---|
master |
19 | 28 | 12,645 | 65.3% | 100% | browse | #8123 | tar.gz |
REL_18_STABLE |
18 | 28 | 12,099 | 69.9% | 100% | browse | #8118 | tar.gz |
REL_17_STABLE |
17 | 28 | 11,510 | 74.9% | 100% | browse | #8119 | tar.gz |
REL_16_STABLE |
16 | 26 | 10,657 | 79.0% | 100% | browse | #8120 | tar.gz |
REL_15_STABLE |
15 | 26 | 10,464 | 85.7% | 100% | browse | #8121 | tar.gz |
REL_14_STABLE |
14 | 26 | 10,126 | 91.8% | 100% | browse | #8122 | tar.gz |
Catalog and message counts are per language and describe the current local
catalogs; download links refer to the dated Simplified Chinese release below.
The upstream percentages describe the initial zh_CN baseline.
The branch names link to the same catalogs as they stand today in the upstream translation repository, pgtranslation/messages.git:
git clone https://git.postgresql.org/git/pgtranslation/messages.gitPostgreSQL 19 lives on master there; there is no REL_19_STABLE. From PG17 on there are two extra catalogs, pg_combinebackup and pg_walsummary — of which pg_combinebackup is a new file for zh_CN.
The links below identify a historical release. To build the current bilingual catalogs locally, see Usage.
Release 20260918 carries one archive per
upstream branch plus the whole set. Each unpacks to zh_CN/<branch>/<catalog>.po, so a
branch directory drops straight into messages.git. Since 20260917 only master has
moved — two new REPACK messages in postgres.po; the other five branches are byte-identical.
| Archive | Covers | Catalogs | Messages |
|---|---|---|---|
pg-messages-zh_CN-20260918.tar.gz |
all six branches | 162 | 67,489 |
pg-messages-zh_CN-master-20260918.tar.gz |
PostgreSQL 19 | 28 | 12,638 |
pg-messages-zh_CN-REL_18_STABLE-20260918.tar.gz |
PostgreSQL 18 | 28 | 12,098 |
pg-messages-zh_CN-REL_17_STABLE-20260918.tar.gz |
PostgreSQL 17 | 28 | 11,509 |
pg-messages-zh_CN-REL_16_STABLE-20260918.tar.gz |
PostgreSQL 16 | 26 | 10,656 |
pg-messages-zh_CN-REL_15_STABLE-20260918.tar.gz |
PostgreSQL 15 | 26 | 10,463 |
pg-messages-zh_CN-REL_14_STABLE-20260918.tar.gz |
PostgreSQL 14 | 26 | 10,125 |
curl -LO https://github.com/pgsty/pgnls/releases/download/20260918/pg-messages-zh_CN-REL_18_STABLE-20260918.tar.gz
tar -xzf pg-messages-zh_CN-REL_18_STABLE-20260918.tar.gz
cp zh_CN/REL_18_STABLE/*.po /path/to/messages/zh_CN/Checksums for every archive are in SHA256SUMS on the same release page.
zh_CN/<branch>/<catalog>.po 162 catalogs, one directory per upstream branch
zh_TW/<branch>/<catalog>.po 162 curated Traditional Chinese catalogs
ref/ style guide, phrasebook, glossaries, process, errata
bin/ standalone tools; Python 3, GNU gettext, GNU tar, gzip
Makefile the usual operations
LICENSE the PostgreSQL License, verbatim from postgres.git
Each view of the catalogs lives on its own branch:
| Branch | Holds | Sync |
|---|---|---|
main |
this curated set, exported from the review database | manual |
message |
the raw state of pgtranslation/messages.git, verbatim |
bin/sync-message.sh on that branch |
babel |
the aligned view babel.postgresql.org serves — the raw catalogs merged against each branch's current POT — as dated snapshots |
bin/sync-babel.sh on that branch |
The two views differ by design: translations on shared msgids are
byte-identical, but the aligned view carries the day's msgid sets (new strings
empty, reworded ones fuzzy-matched, dropped ones as #~) while the raw one
keeps each translator's last word. main also carries the curated zh_TW/
catalogs: 67,501 messages across the same six branches, all translated.
make check validate all 324 zh_CN/zh_TW catalogs (msgfmt, completeness, headers, alignment)
make stats message counts per catalog per branch
make mo compile both languages to .mo under build/<branch>/<language>/LC_MESSAGES/
make dist 15 release tarballs covering both languages, plus SHA256SUMS, under dist/<date>/
make redmine flat catalog files under dist/<date>/redmine/<language>/<branch>/
make fetch-upstream pull a fresh zh_CN snapshot from babel into tmp/
make diff compare zh_CN/ against that snapshot: msgid drift and coverage
make check-align column alignment by East Asian display width, on its own
make show BRANCH=master CATALOG=psql
make clean remove compiled build/ while preserving release assets in dist/
make dist requires GNU tar (gtar on macOS), gzip and shasum. It creates
one bilingual archive, one complete archive per language, and six branch
archives per language, plus SHA256SUMS. Each archive contains only PO files
preserving <language>/<branch>/<catalog>.po. The repository's LICENSE and
compiled MO files are not included. make mo compiles all 324 catalogs separately
for local use.
Set STAMP to choose the release label and DIST to choose the output directory:
STAMP=20260930 make dist
# Or build another copy in a fresh directory:
STAMP=20260930 DIST=/tmp/pgnls-20260930 make distThe default output directory is dist/<STAMP>/. Existing release files are
never overwritten; choose a fresh directory to rebuild. Archive member order,
ownership, permissions and timestamps are normalized, and gzip timestamps are
omitted. SOURCE_DATE_EPOCH defaults to the current Git commit timestamp; when
building an exported source tree without .git, pass that timestamp explicitly.
The same PO files, stamp, epoch and archive tools produce identical archives.
For a PGWeb installation with the language migration applied, generate a language-scoped review bundle from the curated catalogs and the matching Babel snapshot:
python3 bin/pgweb-bundle.py --language zh_TW \
--upstream tmp/babel-snapshot/download/zh_TW --output /tmp/nls-zh_TW.jsonl.gz
# In the pgweb checkout:
.venv/bin/python manage.py nls_import /tmp/nls-zh_TW.jsonl.gz --check
.venv/bin/python manage.py nls_import /tmp/nls-zh_TW.jsonl.gzThe default is PG14–19; repeat --major to select versions. English message sets
must match the snapshot. Candidates start pending, with the Babel translation
kept alongside the curated PO text; review decisions remain independent per
language. Re-importing preserves existing human review state. Historical
zh_CN IDs must be retained when refreshing an existing database; the importer
rejects new IDs for a source message that already exists. Bundle tests run with
python3 -m unittest discover -s tests.
To land these in messages.git, check out the matching branch and overwrite zh_CN/:
cp zh_CN/REL_18_STABLE/*.po /path/to/messages/zh_CN/make redmine prepares separate language and branch directories containing
<catalog>-zh_CN.po or <catalog>-zh_TW.po, using the same bytes as the source
catalogs. Its default output is dist/<STAMP>/redmine/; set OUT to use another
directory. These flat submission files are separate from the release tarballs.
The first commit holds the catalogs exactly as they stand upstream, merged by babel against each branch's current POT so the message sets already match. Every commit after it calibrates one catalog across all of its branches, so the diff for any component reads on its own:
git log --oneline # one commit per catalog
git show <commit> # what changed in that catalog
git diff $(git rev-list --max-parents=0 HEAD) -- zh_CN/master/psql.poMachine-assisted translation, verified and reviewed by a human — not hand
translation, which is what the pgsql-translators thread was told before any of
it started.
A glossary and style guide were fixed first. Each message then went through eight
to ten rounds of translation and cross-review between models (Codex, Astra,
Fable 5.1), every round held to that baseline and gated on msgfmt, placeholder,
plural and column-alignment checks. A complete human review pass came last,
message by message against the English, on the workbench.
The baseline is published in ref/: the style guide (rules R1–R14), the
phrasebook (95 rules, each with the required and forbidden Chinese), two
glossaries and the per-term decision log. ref/process.md has
the long version; ref/errata.md has the known defects.
- Templates — the babel
po-{14..19}-branchsnapshot checked on 2026-09-30. Both languages carry the snapshot's per-filePOT-Creation-Dateand active-message source references (#:).make fetch-upstream && make difftells you at any time whetherzh_CN/still matches the current upstream POT entry for entry. - Only what should change — translation edits affect
msgstrvalues,fuzzyflags, and#|previous-message comments. Explicit template refreshes synchronizePOT-Creation-Dateand source references (#:) while preserving translations andPO-Revision-Date. Extracted comments (#.),msgctxt, other flags, entry order and obsolete#~entries are preserved byte for byte. - Plurals — normalised to the Chinese standard
nplurals=1; plural=0;. The existing headers disagree:postgresandpsqldeclared 1, nine directories declared 2, andlibpqandinitdbcarried plural entries with noPlural-Formsheader at all.pg_dump's circular foreign-key warning uses the number-neutral wording以下表涉及循环外键约束:so the single Chinese plural form covers both self-references within one table and cycles among multiple tables. - Consistency — one glossary governs the whole set, so similar English strings read consistently across every catalog and every branch, which is what makes six branches reviewable as one body of work rather than six.
The current zh_CN and zh_TW catalogs for PostgreSQL 14–19 are a complete
replacement translation produced in 2026. All 324 files use this comment template,
with the language variant and component adjusted to match the file:
# Simplified Chinese message translation file for pg_combinebackup
# Copyright (C) 2026 PostgreSQL Global Development Group
# This file is distributed under the same license as the PostgreSQL package.
#
# Ruohang Feng (vonng@pigsty) <rh@vonng.com>, 2026.
#Historical translator credits precede the current credit. Preserve their names,
email addresses, contribution dates and relative order, using
# Name <email>, YYYY. or # Name <email>, YYYY-MM-DD.. These credits acknowledge
earlier contributions; their dates do not imply participation in the 2026
retranslation. Restore missing credits only from evidence for the same catalog,
such as its historical Last-Translator field. A Language-Team field alone is
not an author list.
The copyright year identifies this complete retranslation; keep it at 2026 for
this edition rather than copying a template's old year or advancing it merely
because the calendar changes. Keep Last-Translator as
Ruohang Feng <rh@vonng.com>; the Pigsty identifier belongs in the author comment.
Set PO-Revision-Date to the actual revision time with its timezone, and preserve
the other machine header fields when changing comments. make check validates
the comment template as well as the machine fields.
The old public-domain comments in Simplified Chinese initdb, pg_config,
pg_ctl and pgscripts came from the early --foreign-user template. PostgreSQL
changed the generator to use PGDG in 2009,
and the Spanish catalogs have a
2010 normalization precedent.
The unified header describes the current retranslation; it does not change the
status of earlier public-domain material. Bao Wei's restored credits in those
four catalogs come from their Last-Translator and revision dates in the
2005 initial import.
Submitted the way the NLS wiki asks for it: one Redmine issue per branch (numbers in the table above), with attachments named <catalog>-zh_CN.po. They supersede #8117, an earlier issue covering the 19 branch alone.
- Where files go — the Redmine patch tracker; issues are readable without an account, filing and commenting need a PostgreSQL community account.
- Where discussion happens —
pgsql-translators@lists.postgresql.org(thread). - Status board — babel.postgresql.org is read-only and accepts no files; its percentages only move once a committer merges into
messages.git.
The translations follow PostgreSQL itself and are available under the PostgreSQL License, the same terms as the software they ship with.
Ruohang Feng <rh@vonng.com> · 2026-09
Catalogs last updated: 2026-09-29 22:12+0800 · zh_CN / zh_TW · PostgreSQL 14–19