feat: i18n support for log and exception messages#820
Conversation
Replace all literal-string exception messages in the tsfile/write package with Messages.get/format calls, adding 46 new keys under the "# === write ===" section in both messages.properties and messages_zh.properties.
Replaces all inline string literals in throw/log statements across the remaining tsfile/read packages (filter, query, reader, v4, and root reader files) with Messages.get/format calls and corresponding keys in messages.properties / messages_zh.properties.
…to i18n keys Replace all literal-string-bearing log/exception messages in the encrypt, compress, fileSystem, and utils sub-packages with Messages.get(key) or Messages.format(key, args). Add aligned keys under four new sections (# === encrypt ===, # === compress ===, # === fileSystem ===, # === utils ===) in both messages.properties and messages_zh.properties.
This site was missed in the original Task 10 commit (bd0b26a) because of an earlier amend issue. The key error.encrypt.sha256_not_found already exists and is used at two other call sites in this same file.
Translate all 521 message values in messages_zh.properties to natural
Simplified Chinese, preserving:
- %1$s positional format specifiers (reordered when natural Chinese
word order differs)
- {} SLF4J placeholders (not reordered)
- Technical terms (TsFile, Chunk, Page, Schema, class/method names,
type names, codec names) kept in English per convention
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## develop #820 +/- ##
===========================================
- Coverage 63.18% 61.11% -2.08%
===========================================
Files 717 732 +15
Lines 43783 45364 +1581
Branches 6526 6740 +214
===========================================
+ Hits 27664 27722 +58
- Misses 15127 16650 +1523
Partials 992 992 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
JackieTien97
left a comment
There was a problem hiding this comment.
Code review
Found 1 issue (3 affected locations): two existing tests assert exact English exception message text for messages that this PR migrates to i18n, so they break under a non-English JVM locale. Each affected source-line is annotated inline below; the unmodified test files are linked from each comment.
Fix options: pin System.setProperty("tsfile.locale", "en") in those tests (same pattern MessagesTest.java already uses), or rewrite the assertions to be locale-insensitive.
🤖 Generated with Claude Code
- If this code review was useful, please react with 👍. Otherwise, react with 👎.
PR #820 review identified that some existing tests assert exact English exception message text, which breaks under a non-English JVM locale. Root-cause investigation revealed two distinct problems: 1. Messages.Utf8Control did not override getFallbackLocale, so when a user explicitly requested "en" via -Dtsfile.locale=en on a JVM with default locale zh_CN, ResourceBundle's default Control would ALSO load the zh bundle as a parent (because the default getFallbackLocale returns Locale.getDefault()). The zh bundle then became the leaf and BUNDLE.getString(key) returned Chinese text despite the en request. Fix: override getFallbackLocale to return null, keeping resolution strictly within the requested locale's candidate chain. 2. Many existing tests in java/tsfile and java/common assert on exact English exception text. Pin tsfile.locale=en via Surefire/Failsafe systemPropertyVariables in both modules so tests run against the English (root) bundle regardless of the developer's JVM default locale. A per-test static-init pattern was attempted first but discarded — class-load timing made it unreliable. Verified under both default locale and -Duser.language=zh -Duser.country=CN: all 854 java/tsfile tests pass; java/common MessagesTest 5/5 passes.
Summary
ResourceBundle-based i18n for all log and exception messages injava/common,java/tsfile, andjava/tools-Dtsfile.locale=zhorLocale.getDefault()messages.propertiesandmessages_zh.propertiesat build timeWhy runtime (vs. compile-time profile)
IoTDB's recent i18n PR (apache/iotdb#17613) uses a Maven profile to inline locale-specific strings into the JAR at compile time. TsFile cannot adopt that same model without either publishing two artifacts per release or forking the version, since downstreams (IoTDB and others) consume tsfile as a versioned dependency. A runtime ResourceBundle approach keeps a single published artifact while letting downstream IoTDB switch locale via a JVM startup option.
Locale resolution order at JVM startup (once at class load):
-Dtsfile.locale=<tag>system property (e.g.zh,zh-CN)Locale.getDefault()ResourceBundle's root-bundle mechanismArchitecture
org.apache.tsfile.i18n.Messages(injava/common) providesget(key)for SLF4J patterns ({}placeholders) andformat(key, args)for exception patterns (%1$spositional placeholders).ResourceBundle.Controlloads.propertiesfiles as UTF-8 (Java 8 default is ISO-8859-1) so Chinese characters can be written directly without\uXXXXescapes.java/common/src/main/resources/org/apache/tsfile/i18n/messages.properties(English, root bundle) andmessages_zh.properties(Chinese).MessagesTestenforces key-set alignment + all values non-empty in both locales.TsFile,Chunk,Page,Schema, class/method names, type names, codec names likeRLE/GORILLA) are kept in English in Chinese translations, matching IoTDB's convention.IoTDB integration
IoTDB's Chinese build (the
with-zh-localeprofile in apache/iotdb#17613) should add-Dtsfile.locale=zhto its startup scripts (e.g.start-datanode.sh,start-confignode.sh) to also receive Chinese messages from tsfile. No coordinated release is required — IoTDB can adopt this whenever convenient.Migration scope
Migrated all literal-string log and exception messages in:
commontsfile/writetsfile/read/commontsfile/read(rest)tsfile/encodingtsfile/filetsfile/externaltsfile/encrypttsfile/compresstsfile/fileSystemtsfile/utilstoolsEach migration commit is its own logical scope so reviewers can review per-area.
Sites correctly skipped (not migrated):
throw new X(deviceId.toString()),throw new X(String.valueOf(type)),throw new X(getClass().getName())throw new X(e)throw new X()Validate.isTrue(boolean, String, Object...))Test plan
./mvnw test -P with-javaMessagesTestdrift-prevention tests pass — verifies en/zh key set alignment + all values non-emptyMessagesTestpasses under-Duser.language=zh -Duser.country=CN(simulated Chinese locale)-Dtsfile.locale=zhshow Chinese output without test failures./mvnw spotless:check -P with-javaclean.propertiesfile