Skip to content

Commit f797f85

Browse files
authored
feat: add compile-time i18n for log and exception messages (#17613)
1 parent e81a432 commit f797f85

1,383 files changed

Lines changed: 31832 additions & 7010 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/compile-check.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,3 +53,7 @@ jobs:
5353
shell: bash
5454
run: |
5555
mvn clean package -P with-integration-tests -DskipTests -ntp
56+
- name: Compiler Test (Chinese i18n)
57+
shell: bash
58+
run: |
59+
mvn clean package -P with-integration-tests,with-zh-locale -DskipTests -ntp

CLAUDE.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,9 @@ mvn clean test -pl iotdb-core/datanode -Dtest=ClassName
4545
# Run a single test method
4646
mvn clean test -pl iotdb-core/datanode -Dtest=ClassName#methodName
4747

48+
# Build with Chinese log & error messages
49+
mvn clean package -pl distribution -am -DskipTests -P with-zh-locale
50+
4851
# Format code (requires JDK 17+; auto-skipped on JDK <17)
4952
mvn spotless:apply
5053

@@ -170,6 +173,10 @@ Generated source directories that need to be on the source path:
170173
- **Missing Thrift compiler**: The local machine may not have the `thrift` binary installed. Running `mvn clean package -pl <module> -am -DskipTests` will fail at the `iotdb-thrift` module. **Workaround**: To verify your changes compile, use `mvn compile -pl <module>` (without `-am` or `clean`) to leverage existing target caches.
171174
- **Pre-existing compilation errors in unrelated modules**: The datanode module may have pre-existing compile errors in other subsystems (e.g., pipe, copyto) that cause `mvn clean test -pl iotdb-core/datanode -Dtest=XxxTest` to fail during compilation. **Workaround**: First run `mvn compile -pl iotdb-core/datanode` to confirm your changed files compile successfully. If the errors are in files you did not modify, they are pre-existing and do not affect your changes.
172175

176+
### i18n (Chinese Messages)
177+
178+
The project uses compile-time i18n via the `build-helper-maven-plugin`. The property `i18n.locale` (default: `en`) controls which source directory is added: `src/main/i18n/${i18n.locale}`. Activating `-P with-zh-locale` sets `i18n.locale=zh`, swapping English message constant classes for Chinese ones. Each module that participates has both `src/main/i18n/en/` and `src/main/i18n/zh/` directories containing Java classes with identical structure but different string literals.
179+
173180
### Code Style
174181

175182
- **Always run `mvn spotless:apply` after editing Java files**: Spotless runs `spotless:check` automatically during the `compile` phase. Format violations cause an immediate BUILD FAILURE. Make it a habit to run `mvn spotless:apply -pl <module>` right after editing, not at the end. For files under `integration-test/`, add `-P with-integration-tests`.

README.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,16 @@ Under the iotdb/iotdb-client path:
314314
315315
After being built, the IoTDB cli is located at the folder "cli/target".
316316
317+
### Build with Chinese Log & Error Messages
318+
319+
IoTDB supports compile-time internationalization (i18n) for log and error messages. By default, messages are in English. To build with Chinese messages, activate the `with-zh-locale` Maven profile:
320+
321+
```
322+
> mvn clean package -pl distribution -am -DskipTests -P with-zh-locale
323+
```
324+
325+
This works by swapping the source directory `src/main/i18n/en` (default) with `src/main/i18n/zh`, where each module keeps locale-specific Java constant classes containing translated message strings.
326+
317327
### Build Others
318328
319329
Use `-P with-cpp` for compiling the cpp client. (For more details, read client-cpp's Readme file.)

README_ZH.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,16 @@ git checkout rel/x.x
170170
171171
编译完成后, IoTDB cli 将生成在 "cli/target".
172172
173+
### 编译中文日志和错误信息版本
174+
175+
IoTDB 支持编译时国际化(i18n),可将日志和错误信息切换为中文。默认编译使用英文,如需中文版本,请激活 `with-zh-locale` Maven profile:
176+
177+
```
178+
> mvn clean package -pl distribution -am -DskipTests -P with-zh-locale
179+
```
180+
181+
该机制通过在编译时将源码目录从 `src/main/i18n/en`(默认)替换为 `src/main/i18n/zh` 实现,各模块在对应目录下维护翻译后的 Java 消息常量类。
182+
173183
### 编译其他模块
174184
175185
通过添加 `-P with-cpp` 可以进行c++客户端API的编译。

external-service-impl/mqtt/pom.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,10 @@
172172
</ignoredDependencies>
173173
</configuration>
174174
</plugin>
175+
<plugin>
176+
<groupId>org.codehaus.mojo</groupId>
177+
<artifactId>build-helper-maven-plugin</artifactId>
178+
</plugin>
175179
</plugins>
176180
</build>
177181
</project>
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
package org.apache.iotdb.mqtt.i18n;
21+
22+
public final class MqttMessages {
23+
24+
// --- LinePayloadFormatter ---
25+
public static final String INVALID_LINE_PROTOCOL = "Invalid line protocol format ,line is {}";
26+
public static final String TAGS_ERROR = "The tags is error , line is {}";
27+
public static final String ATTRIBUTES_ERROR = "The attributes is error , line is {}";
28+
public static final String FIELDS_ERROR = "The fields is error , line is {}";
29+
public static final String TIMESTAMP_ERROR = "The timestamp is error , line is {}";
30+
31+
// --- MPPPublishHandler ---
32+
public static final String ON_PUBLISH_EXCEPTION =
33+
"onPublish execution exception, msg is [{}], error is ";
34+
public static final String PROCESS_RESULT = "process result: {}";
35+
36+
// --- MQTTService ---
37+
public static final String SERVER_START_EXCEPTION = "Exception while starting server";
38+
public static final String STOPPING_MQTT_SERVICE = "Stopping IoTDB MQTT service...";
39+
public static final String MQTT_SERVICE_STOPPED = "IoTDB MQTT service stopped.";
40+
41+
// --- PayloadFormatManager ---
42+
public static final String MQTT_DIR = "mqttDir: {}";
43+
public static final String PAYLOAD_FORMAT_MANAGER_INIT_ERROR =
44+
"MQTT PayloadFormatManager init() error.";
45+
public static final String FORMATTER_IS_NULL = "PayloadFormatManager(), formatter is null.";
46+
public static final String FIND_MQTT_PLUGIN =
47+
"PayloadFormatManager(), find MQTT Payload Plugin {}.";
48+
public static final String MQTT_PLUGIN_JAR_URLS = "MQTT Plugin jarURLs: {}";
49+
50+
// --- JSONPayloadFormatter ---
51+
public static final String PAYLOAD_INVALID = "payload is invalidate";
52+
53+
private MqttMessages() {}
54+
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
package org.apache.iotdb.mqtt.i18n;
21+
22+
public final class MqttMessages {
23+
24+
// --- LinePayloadFormatter ---
25+
public static final String INVALID_LINE_PROTOCOL = "行协议格式无效,行内容:{}";
26+
public static final String TAGS_ERROR = "标签格式错误,行内容:{}";
27+
public static final String ATTRIBUTES_ERROR = "属性格式错误,行内容:{}";
28+
public static final String FIELDS_ERROR = "字段格式错误,行内容:{}";
29+
public static final String TIMESTAMP_ERROR = "时间戳格式错误,行内容:{}";
30+
31+
// --- MPPPublishHandler ---
32+
public static final String ON_PUBLISH_EXCEPTION =
33+
"onPublish 执行异常,消息为 [{}],错误:";
34+
public static final String PROCESS_RESULT = "处理结果:{}";
35+
36+
// --- MQTTService ---
37+
public static final String SERVER_START_EXCEPTION = "启动服务器时发生异常";
38+
public static final String STOPPING_MQTT_SERVICE = "正在停止 IoTDB MQTT 服务...";
39+
public static final String MQTT_SERVICE_STOPPED = "IoTDB MQTT 服务已停止。";
40+
41+
// --- PayloadFormatManager ---
42+
public static final String MQTT_DIR = "mqttDir:{}";
43+
public static final String PAYLOAD_FORMAT_MANAGER_INIT_ERROR =
44+
"MQTT PayloadFormatManager init() 出错。";
45+
public static final String FORMATTER_IS_NULL = "PayloadFormatManager(),formatter 为 null。";
46+
public static final String FIND_MQTT_PLUGIN =
47+
"PayloadFormatManager(),找到 MQTT Payload 插件 {}。";
48+
public static final String MQTT_PLUGIN_JAR_URLS = "MQTT 插件 jarURLs:{}";
49+
50+
// --- JSONPayloadFormatter ---
51+
public static final String PAYLOAD_INVALID = "payload 无效";
52+
53+
private MqttMessages() {}
54+
}

external-service-impl/mqtt/src/main/java/org/apache/iotdb/mqtt/JSONPayloadFormatter.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818

1919
package org.apache.iotdb.mqtt;
2020

21+
import org.apache.iotdb.mqtt.i18n.MqttMessages;
22+
2123
import com.google.common.collect.Lists;
2224
import com.google.gson.Gson;
2325
import com.google.gson.GsonBuilder;
@@ -79,7 +81,7 @@ public List<Message> format(String topic, ByteBuf payload) {
7981
}
8082
return messages;
8183
}
82-
throw new JsonParseException("payload is invalidate");
84+
throw new JsonParseException(MqttMessages.PAYLOAD_INVALID);
8385
}
8486

8587
@Override

external-service-impl/mqtt/src/main/java/org/apache/iotdb/mqtt/LinePayloadFormatter.java

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818

1919
package org.apache.iotdb.mqtt;
2020

21+
import org.apache.iotdb.mqtt.i18n.MqttMessages;
22+
2123
import io.netty.buffer.ByteBuf;
2224
import org.apache.tsfile.enums.TSDataType;
2325
import org.apache.tsfile.external.commons.lang3.NotImplementedException;
@@ -83,7 +85,7 @@ public List<Message> format(String topic, ByteBuf payload) {
8385
try {
8486
Matcher matcher = pattern.matcher(line.trim());
8587
if (!matcher.matches()) {
86-
log.warn("Invalid line protocol format ,line is {}", line);
88+
log.warn(MqttMessages.INVALID_LINE_PROTOCOL, line);
8789
continue;
8890
}
8991

@@ -95,25 +97,25 @@ public List<Message> format(String topic, ByteBuf payload) {
9597

9698
// Parsing Tags
9799
if (!setTags(matcher, message)) {
98-
log.warn("The tags is error , line is {}", line);
100+
log.warn(MqttMessages.TAGS_ERROR, line);
99101
continue;
100102
}
101103

102104
// Parsing Attributes
103105
if (!setAttributes(matcher, message)) {
104-
log.warn("The attributes is error , line is {}", line);
106+
log.warn(MqttMessages.ATTRIBUTES_ERROR, line);
105107
continue;
106108
}
107109

108110
// Parsing Fields
109111
if (!setFields(matcher, message)) {
110-
log.warn("The fields is error , line is {}", line);
112+
log.warn(MqttMessages.FIELDS_ERROR, line);
111113
continue;
112114
}
113115

114116
// Parsing timestamp
115117
if (!setTimestamp(matcher, message)) {
116-
log.warn("The timestamp is error , line is {}", line);
118+
log.warn(MqttMessages.TIMESTAMP_ERROR, line);
117119
continue;
118120
}
119121

external-service-impl/mqtt/src/main/java/org/apache/iotdb/mqtt/MPPPublishHandler.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
import org.apache.iotdb.db.queryengine.plan.statement.crud.InsertRowStatement;
4444
import org.apache.iotdb.db.queryengine.plan.statement.crud.InsertTabletStatement;
4545
import org.apache.iotdb.db.utils.CommonUtils;
46+
import org.apache.iotdb.mqtt.i18n.MqttMessages;
4647
import org.apache.iotdb.rpc.TSStatusCode;
4748
import org.apache.iotdb.service.rpc.thrift.TSProtocolVersion;
4849

@@ -159,7 +160,7 @@ public void onPublish(InterceptPublishMessage msg) {
159160
}
160161
}
161162
} catch (Throwable t) {
162-
LOG.warn("onPublish execution exception, msg is [{}], error is ", msg, t);
163+
LOG.warn(MqttMessages.ON_PUBLISH_EXCEPTION, msg, t);
163164
} finally {
164165
// release the payload of the message
165166
super.onPublish(msg);
@@ -191,7 +192,7 @@ private void insertTable(TableMessage message, MqttClientSession session) {
191192

192193
tsStatus = result.status;
193194
if (LOG.isDebugEnabled()) {
194-
LOG.debug("process result: {}", tsStatus);
195+
LOG.debug(MqttMessages.PROCESS_RESULT, tsStatus);
195196
}
196197
if (tsStatus.getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()
197198
&& tsStatus.getCode() != TSStatusCode.REDIRECTION_RECOMMEND.getStatusCode()) {
@@ -310,7 +311,7 @@ private void insertTree(TreeMessage message, MqttClientSession session) {
310311
false);
311312
tsStatus = result.status;
312313
if (LOG.isDebugEnabled()) {
313-
LOG.debug("process result: {}", tsStatus);
314+
LOG.debug(MqttMessages.PROCESS_RESULT, tsStatus);
314315
}
315316
if (tsStatus.getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()
316317
&& tsStatus.getCode() != TSStatusCode.REDIRECTION_RECOMMEND.getStatusCode()) {

0 commit comments

Comments
 (0)