This is an automated email from the ASF dual-hosted git repository.

chaokunyang pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/fory.git


The following commit(s) were added to refs/heads/main by this push:
     new 34e6c2982 refactor(spec): remove language byte from xlang in protocol 
(#3256)
34e6c2982 is described below

commit 34e6c2982c959f664d530b4016e63239142c3cc1
Author: Shawn Yang <[email protected]>
AuthorDate: Wed Feb 4 06:57:23 2026 +0800

    refactor(spec): remove language byte from xlang in protocol (#3256)
    
    ## Why?
    
    The xlang header no longer needs a per-language byte, and the
    ref-tracking naming has drifted across implementations. Align the
    protocol header and configuration to be consistent across languages.
    
    ## What does this PR do?
    
    - Removes the xlang language byte and updates header write/read paths in
    Java, C++, Python, Go, JS, Dart, and Rust to use a single-byte bitmap.
    - Simplifies language/config plumbing (Java config uses an `xlang` flag;
    language enums/constants removed where unused).
    - Renames/refactors ref-tracking fields to `track_ref`/`ref` across
    languages and updates fingerprints, serializers, tests, and docs/specs.
    
    ## Related issues
    
    #1017
    
    ## Does this PR introduce any user-facing change?
    
    Yes — the xlang wire header changes and ref-tracking/config naming
    updates are user-visible.
    
    - [x] Does this PR introduce any public API change?
    - [x] Does this PR introduce any binary protocol compatibility change?
    
    ## Benchmark
---
 cpp/fory/serialization/fory.h                      | 26 ++++------
 cpp/fory/serialization/ref_mode.h                  |  6 +--
 cpp/fory/serialization/serialization_test.cc       | 22 ++++----
 cpp/fory/serialization/serializer.h                | 28 ----------
 cpp/fory/serialization/skip.cc                     |  2 +-
 cpp/fory/serialization/struct_serializer.h         |  2 +-
 cpp/fory/serialization/type_resolver.cc            | 14 ++---
 cpp/fory/serialization/type_resolver.h             | 57 +++++++++++---------
 dart/packages/fory/lib/fory.dart                   |  1 -
 dart/packages/fory/lib/src/const/lang.dart         | 33 ------------
 .../lib/src/serializer/fory_header_serializer.dart | 17 ------
 docs/guide/java/cross-language.md                  |  2 +-
 docs/guide/rust/cross-language.md                  |  2 +-
 docs/guide/xlang/field-reference-tracking.md       |  4 +-
 docs/guide/xlang/getting-started.md                |  2 +-
 docs/guide/xlang/serialization.md                  |  2 +-
 docs/guide/xlang/troubleshooting.md                |  2 +-
 docs/specification/java_serialization_spec.md      |  3 +-
 docs/specification/xlang_serialization_spec.md     | 23 ++-------
 go/fory/fory.go                                    | 12 -----
 go/fory/struct.go                                  |  2 +-
 .../src/main/java/org/apache/fory/Fory.java        | 36 +++----------
 .../apache/fory/builder/ObjectCodecOptimizer.java  |  6 +--
 .../main/java/org/apache/fory/config/Config.java   | 12 ++---
 .../java/org/apache/fory/config/ForyBuilder.java   | 20 ++++----
 .../main/java/org/apache/fory/config/Language.java |  6 ---
 .../src/test/java/org/apache/fory/ForyTest.java    |  2 +-
 .../fory/serializer/ArraySerializersTest.java      |  2 +-
 javascript/packages/fory/lib/fory.ts               |  4 +-
 javascript/packages/fory/lib/type.ts               | 11 ----
 python/pyfory/__init__.py                          |  8 ---
 python/pyfory/_fory.py                             | 47 ++++-------------
 python/pyfory/_serializer.py                       |  2 +-
 python/pyfory/collection.pxi                       | 34 ++++++------
 python/pyfory/collection.py                        | 42 ++++++++-------
 python/pyfory/field.py                             |  2 +-
 python/pyfory/meta/typedef.py                      | 14 ++---
 python/pyfory/registry.py                          | 21 ++++----
 python/pyfory/serialization.pyx                    | 60 ++++++++--------------
 python/pyfory/serializer.py                        |  4 +-
 python/pyfory/struct.py                            |  8 +--
 python/pyfory/tests/test_cross_language.py         |  2 +-
 python/pyfory/tests/test_method.py                 |  2 +-
 python/pyfory/tests/test_serializer.py             | 48 +++++++++--------
 python/pyfory/tests/test_struct.py                 |  2 +-
 python/pyfory/tests/test_union.py                  |  4 +-
 rust/fory-core/src/fory.rs                         | 16 ++----
 rust/fory-core/src/meta/type_meta.rs               | 34 ++++++------
 rust/fory-core/src/serializer/skip.rs              | 26 +++++-----
 rust/fory-core/src/types.rs                        | 32 ------------
 rust/fory-derive/src/object/misc.rs                | 20 ++++----
 rust/fory-derive/src/object/read.rs                | 48 ++++++++---------
 rust/fory-derive/src/object/util.rs                | 16 +++---
 rust/tests/tests/test_meta.rs                      |  2 +-
 54 files changed, 299 insertions(+), 556 deletions(-)

diff --git a/cpp/fory/serialization/fory.h b/cpp/fory/serialization/fory.h
index eb683cb0e..8b1428c96 100644
--- a/cpp/fory/serialization/fory.h
+++ b/cpp/fory/serialization/fory.h
@@ -586,16 +586,14 @@ private:
   /// Constructor for ForyBuilder - resolver will be finalized lazily.
   explicit Fory(const Config &config, std::shared_ptr<TypeResolver> resolver)
       : BaseFory(config, std::move(resolver)), finalized_(false),
-        precomputed_header_(compute_header(config.xlang)),
-        header_length_(config.xlang ? 2 : 1) {}
+        precomputed_header_(compute_header(config.xlang)) {}
 
   /// Constructor for ThreadSafeFory pool - resolver is already finalized.
   struct PreFinalized {};
   explicit Fory(const Config &config, std::shared_ptr<TypeResolver> resolver,
                 PreFinalized)
       : BaseFory(config, std::move(resolver)), finalized_(false),
-        precomputed_header_(compute_header(config.xlang)),
-        header_length_(config.xlang ? 2 : 1) {
+        precomputed_header_(compute_header(config.xlang)) {
     // Pre-finalized, immediately create contexts
     ensure_finalized();
   }
@@ -619,17 +617,12 @@ private:
   }
 
   /// Compute the precomputed header value.
-  static uint16_t compute_header(bool xlang) {
-    uint16_t header = 0;
-    // Flags byte at position 0
+  static uint8_t compute_header(bool xlang) {
     uint8_t flags = 0;
     if (xlang) {
       flags |= (1 << 1); // bit 1: xlang flag
     }
-    header |= flags;
-    // Language byte at position 1 (only used if xlang)
-    header |= (static_cast<uint16_t>(Language::CPP) << 8);
-    return header;
+    return flags;
   }
 
   /// Core serialization implementation.
@@ -638,10 +631,10 @@ private:
   Result<size_t, Error> serialize_impl(const T &obj, Buffer &buffer) {
     size_t start_pos = buffer.writer_index();
 
-    // write precomputed header (2 bytes), then adjust index if not xlang
-    buffer.grow(2);
-    buffer.unsafe_put<uint16_t>(buffer.writer_index(), precomputed_header_);
-    buffer.increase_writer_index(header_length_);
+    // write precomputed header (1 byte flags)
+    buffer.grow(1);
+    buffer.unsafe_put_byte(buffer.writer_index(), precomputed_header_);
+    buffer.increase_writer_index(1);
 
     // Top-level serialization: use Tracking if ref tracking is enabled,
     // otherwise NullOnly for nullable handling
@@ -676,8 +669,7 @@ private:
   }
 
   bool finalized_;
-  uint16_t precomputed_header_;
-  uint8_t header_length_;
+  uint8_t precomputed_header_;
   std::optional<WriteContext> write_ctx_;
   std::optional<ReadContext> read_ctx_;
 
diff --git a/cpp/fory/serialization/ref_mode.h 
b/cpp/fory/serialization/ref_mode.h
index 2482c1771..736a6bf34 100644
--- a/cpp/fory/serialization/ref_mode.h
+++ b/cpp/fory/serialization/ref_mode.h
@@ -48,11 +48,11 @@ enum class RefMode : uint8_t {
   Tracking = 2,
 };
 
-/// Create RefMode from nullable and ref_tracking flags.
+/// Create RefMode from nullable and track_ref flags.
 /// This is a constexpr function for compile-time field metadata conversion.
 FORY_ALWAYS_INLINE constexpr RefMode make_ref_mode(bool nullable,
-                                                   bool ref_tracking) {
-  if (ref_tracking) {
+                                                   bool track_ref) {
+  if (track_ref) {
     return RefMode::Tracking;
   }
   if (nullable) {
diff --git a/cpp/fory/serialization/serialization_test.cc 
b/cpp/fory/serialization/serialization_test.cc
index a089b0b2a..110b75daf 100644
--- a/cpp/fory/serialization/serialization_test.cc
+++ b/cpp/fory/serialization/serialization_test.cc
@@ -236,10 +236,10 @@ TEST(SerializationTest, EnumSerializesOrdinalValue) {
   std::vector<uint8_t> bytes = bytes_result.value();
   // Xlang spec: enums are serialized as varuint32, not fixed int32_t.
   // With registration, we write type_id (ENUM) + user_type_id (1), both as
-  // varuint32. Expected: 2 (header) + 1 (ref flag) + 1 (type id) +
-  // 1 (user type id) + 1 (ordinal) = 6 bytes
-  ASSERT_GE(bytes.size(), 2 + 1 + 1 + 1 + 1);
-  size_t offset = 2;
+  // varuint32. Expected: 1 (header) + 1 (ref flag) + 1 (type id) +
+  // 1 (user type id) + 1 (ordinal) = 5 bytes
+  ASSERT_GE(bytes.size(), 1 + 1 + 1 + 1 + 1);
+  size_t offset = 1;
   EXPECT_EQ(bytes[offset], static_cast<uint8_t>(NOT_NULL_VALUE_FLAG));
   EXPECT_EQ(bytes[offset + 1], static_cast<uint8_t>(TypeId::ENUM));
   EXPECT_EQ(bytes[offset + 2], 1);
@@ -257,8 +257,8 @@ TEST(SerializationTest, OldEnumSerializesOrdinalValue) {
 
   std::vector<uint8_t> bytes = bytes_result.value();
   // With registration, type_id + user_type_id take 2 bytes
-  ASSERT_GE(bytes.size(), 2 + 1 + 1 + 1 + 1);
-  size_t offset = 2;
+  ASSERT_GE(bytes.size(), 1 + 1 + 1 + 1 + 1);
+  size_t offset = 1;
   EXPECT_EQ(bytes[offset], static_cast<uint8_t>(NOT_NULL_VALUE_FLAG));
   EXPECT_EQ(bytes[offset + 1], static_cast<uint8_t>(TypeId::ENUM));
   EXPECT_EQ(bytes[offset + 2], 1);
@@ -276,8 +276,8 @@ TEST(SerializationTest, 
EnumOrdinalMappingHandlesNonZeroStart) {
 
   std::vector<uint8_t> bytes = bytes_result.value();
   // With registration, type_id + user_type_id take 2 bytes
-  ASSERT_GE(bytes.size(), 2 + 1 + 1 + 1 + 1);
-  size_t offset = 2;
+  ASSERT_GE(bytes.size(), 1 + 1 + 1 + 1 + 1);
+  size_t offset = 1;
   EXPECT_EQ(bytes[offset], static_cast<uint8_t>(NOT_NULL_VALUE_FLAG));
   EXPECT_EQ(bytes[offset + 1], static_cast<uint8_t>(TypeId::ENUM));
   EXPECT_EQ(bytes[offset + 2], 1);
@@ -299,7 +299,7 @@ TEST(SerializationTest, 
EnumOrdinalMappingRejectsInvalidOrdinal) {
       << "Serialization failed: " << bytes_result.error().to_string();
 
   std::vector<uint8_t> bytes = bytes_result.value();
-  size_t offset = 2;
+  size_t offset = 1;
   // With registration, type_id + user_type_id take 2 bytes, ordinal is at
   // offset + 3 Replace the valid ordinal with an invalid one (99 as varuint32)
   bytes[offset + 3] = 99;
@@ -318,8 +318,8 @@ TEST(SerializationTest, 
OldEnumOrdinalMappingHandlesNonZeroStart) {
 
   std::vector<uint8_t> bytes = bytes_result.value();
   // With registration, type_id + user_type_id take 2 bytes
-  ASSERT_GE(bytes.size(), 2 + 1 + 1 + 1 + 1);
-  size_t offset = 2;
+  ASSERT_GE(bytes.size(), 1 + 1 + 1 + 1 + 1);
+  size_t offset = 1;
   EXPECT_EQ(bytes[offset], static_cast<uint8_t>(NOT_NULL_VALUE_FLAG));
   EXPECT_EQ(bytes[offset + 1], static_cast<uint8_t>(TypeId::ENUM));
   EXPECT_EQ(bytes[offset + 2], 1);
diff --git a/cpp/fory/serialization/serializer.h 
b/cpp/fory/serialization/serializer.h
index 173576976..5eeae493e 100644
--- a/cpp/fory/serialization/serializer.h
+++ b/cpp/fory/serialization/serializer.h
@@ -60,21 +60,6 @@ namespace serialization {
 // Protocol Constants
 // ============================================================================
 
-/// Language identifiers
-/// Must match Java's Language enum ordinal values
-enum class Language : uint8_t {
-  XLANG = 0,
-  JAVA = 1,
-  PYTHON = 2,
-  CPP = 3,
-  GO = 4,
-  JAVASCRIPT = 5,
-  RUST = 6,
-  DART = 7,
-  SCALA = 8,
-  KOTLIN = 9,
-};
-
 /// Detect if system is little endian
 inline bool is_little_endian_system() {
   uint32_t test = 1;
@@ -90,7 +75,6 @@ struct HeaderInfo {
   bool is_null;
   bool is_xlang;
   bool is_oob;
-  Language language;
   uint32_t meta_start_offset; // 0 if not present
 };
 
@@ -117,18 +101,6 @@ inline Result<HeaderInfo, Error> read_header(Buffer 
&buffer) {
   // Update reader index (1 byte consumed: flags)
   buffer.increase_reader_index(1);
 
-  // Language byte after header in xlang mode
-  if (info.is_xlang) {
-    Error error;
-    uint8_t lang_byte = buffer.read_uint8(error);
-    if (FORY_PREDICT_FALSE(!error.ok())) {
-      return Unexpected(std::move(error));
-    }
-    info.language = static_cast<Language>(lang_byte);
-  } else {
-    info.language = Language::JAVA;
-  }
-
   // Note: Meta start offset would be read here if present
   info.meta_start_offset = 0;
 
diff --git a/cpp/fory/serialization/skip.cc b/cpp/fory/serialization/skip.cc
index 1941b7dd6..9209c4ae8 100644
--- a/cpp/fory/serialization/skip.cc
+++ b/cpp/fory/serialization/skip.cc
@@ -29,7 +29,7 @@ namespace {
 // Compute RefMode from field type at runtime.
 //
 // Per xlang protocol and Java's ObjectSerializer.write_other_field_value:
-// - In xlang mode with ref_tracking=false (default), fields only write
+// - In xlang mode with ref=false (default), fields only write
 //   ref/null flag if they are nullable
 // - Primitives never have ref flags (handled separately)
 } // namespace
diff --git a/cpp/fory/serialization/struct_serializer.h 
b/cpp/fory/serialization/struct_serializer.h
index 7c7e5ae35..408a288b0 100644
--- a/cpp/fory/serialization/struct_serializer.h
+++ b/cpp/fory/serialization/struct_serializer.h
@@ -2751,7 +2751,7 @@ void read_struct_fields_compatible(T &obj, ReadContext 
&ctx,
     int16_t field_id = remote_field.field_id;
 
     // Use the precomputed ref_mode from remote field metadata.
-    // This is computed from nullable and ref_tracking flags in the remote
+    // This is computed from nullable and track_ref flags in the remote
     // field's header during FieldInfo::from_bytes.
     RefMode remote_ref_mode = remote_field.field_type.ref_mode;
     if (field_id == -1) {
diff --git a/cpp/fory/serialization/type_resolver.cc 
b/cpp/fory/serialization/type_resolver.cc
index dbfa69623..a205723d0 100644
--- a/cpp/fory/serialization/type_resolver.cc
+++ b/cpp/fory/serialization/type_resolver.cc
@@ -94,7 +94,7 @@ Result<FieldType, Error> FieldType::read_from(Buffer &buffer, 
bool read_flag,
   bool null;
   bool ref_track;
   if (read_flag) {
-    // Header layout: type_id:N bits | nullable:1 bit | ref_tracking:1 bit
+    // Header layout: type_id:N bits | nullable:1 bit | track_ref:1 bit
     tid = header >> 2;
     null = (header & 0b10) != 0;
     ref_track = (header & 0b01) != 0;
@@ -131,7 +131,7 @@ Result<std::vector<uint8_t>, Error> FieldInfo::to_bytes() 
const {
 
   // write field header:
   // header: | field_name_encoding:2bits | size:4bits | nullability:1bit |
-  // ref_tracking:1bit |
+  // track_ref:1bit |
   const bool use_tag_id = field_id >= 0;
   uint8_t encoding_idx = use_tag_id ? 3 : 0; // TAG_ID or UTF8
   std::vector<uint8_t> encoded_name;
@@ -165,7 +165,7 @@ Result<std::vector<uint8_t>, Error> FieldInfo::to_bytes() 
const {
   uint8_t header =
       (std::min(FIELD_NAME_SIZE_THRESHOLD, name_size - 1) << 2) & 0x3C;
 
-  if (field_type.ref_tracking) {
+  if (field_type.track_ref) {
     header |= 1; // bit 0 for ref tracking
   }
   if (field_type.nullable) {
@@ -207,7 +207,7 @@ Result<FieldInfo, Error> FieldInfo::from_bytes(Buffer 
&buffer) {
   // bits 6-7: field name encoding index
   uint8_t encoding_idx = static_cast<uint8_t>(header >> 6);
   bool use_tag_id = encoding_idx == 3;
-  bool ref_tracking = (header & 0b01u) != 0;
+  bool track_ref = (header & 0b01u) != 0;
   bool nullable = (header & 0b10u) != 0;
   size_t name_size = ((header >> 2) & FIELD_NAME_SIZE_THRESHOLD);
   if (name_size == FIELD_NAME_SIZE_THRESHOLD) {
@@ -219,9 +219,9 @@ Result<FieldInfo, Error> FieldInfo::from_bytes(Buffer 
&buffer) {
   }
   name_size += 1;
 
-  // Read field type with nullable and ref_tracking from header
+  // Read field type with nullable and track_ref from header
   FORY_TRY(field_type,
-           FieldType::read_from(buffer, false, nullable, ref_tracking));
+           FieldType::read_from(buffer, false, nullable, track_ref));
 
   if (use_tag_id) {
     FieldInfo info("", std::move(field_type));
@@ -1196,7 +1196,7 @@ std::string TypeMeta::compute_struct_fingerprint(
     fingerprint.append(std::to_string(effective_type_id));
     fingerprint.push_back(',');
     // Use field-level ref tracking flag from FORY_FIELD_TAGS or fory::field<>
-    fingerprint.push_back(fi.field_type.ref_tracking ? '1' : '0');
+    fingerprint.push_back(fi.field_type.track_ref ? '1' : '0');
     fingerprint.push_back(',');
     fingerprint.append(fi.field_type.nullable ? "1;" : "0;");
   }
diff --git a/cpp/fory/serialization/type_resolver.h 
b/cpp/fory/serialization/type_resolver.h
index 2a8e61d87..cd237c8f7 100644
--- a/cpp/fory/serialization/type_resolver.h
+++ b/cpp/fory/serialization/type_resolver.h
@@ -108,19 +108,19 @@ public:
   // Stored as unsigned; 0xffffffff means "unset".
   uint32_t user_type_id;
   bool nullable;
-  bool ref_tracking;
-  RefMode ref_mode; // Precomputed from nullable and ref_tracking
+  bool track_ref;
+  RefMode ref_mode; // Precomputed from nullable and track_ref
   std::vector<FieldType> generics;
 
   FieldType()
       : type_id(0), user_type_id(kInvalidUserTypeId), nullable(false),
-        ref_tracking(false), ref_mode(RefMode::None) {}
+        track_ref(false), ref_mode(RefMode::None) {}
 
   FieldType(uint32_t tid, bool null, bool ref_track = false,
             std::vector<FieldType> gens = {},
             uint32_t user_tid = kInvalidUserTypeId)
       : type_id(tid), user_type_id(user_tid), nullable(null),
-        ref_tracking(ref_track), ref_mode(make_ref_mode(null, ref_track)),
+        track_ref(ref_track), ref_mode(make_ref_mode(null, ref_track)),
         generics(std::move(gens)) {}
 
   /// write field type to buffer
@@ -141,8 +141,8 @@ public:
 
   bool operator==(const FieldType &other) const {
     return type_id == other.type_id && nullable == other.nullable &&
-           user_type_id == other.user_type_id &&
-           ref_tracking == other.ref_tracking && generics == other.generics;
+           user_type_id == other.user_type_id && track_ref == other.track_ref 
&&
+           generics == other.generics;
   }
 
   bool operator!=(const FieldType &other) const { return !(*this == other); }
@@ -630,20 +630,31 @@ Result<FieldType, Error> 
build_field_type_with_resolver(TypeResolver &resolver,
   } else {
     FieldType ft = FieldTypeBuilder<Decayed>::build(nullable);
     if (is_user_type(static_cast<TypeId>(ft.type_id))) {
-      FORY_TRY(info, get_type_info_with_resolver<Decayed>(resolver));
-      uint32_t resolved_type_id = info->type_id;
-      switch (static_cast<TypeId>(resolved_type_id)) {
-      case TypeId::NAMED_ENUM:
-        resolved_type_id = static_cast<uint32_t>(TypeId::ENUM);
-        break;
-      case TypeId::TYPED_UNION:
-      case TypeId::NAMED_UNION:
-        resolved_type_id = static_cast<uint32_t>(TypeId::UNION);
-        break;
-      default:
-        break;
+      if constexpr (std::is_enum_v<Decayed>) {
+        auto info_result = get_type_info_with_resolver<Decayed>(resolver);
+        if (info_result.ok()) {
+          uint32_t resolved_type_id = info_result.value()->type_id;
+          if (resolved_type_id == static_cast<uint32_t>(TypeId::NAMED_ENUM)) {
+            resolved_type_id = static_cast<uint32_t>(TypeId::ENUM);
+          }
+          ft.type_id = resolved_type_id;
+        }
+      } else {
+        FORY_TRY(info, get_type_info_with_resolver<Decayed>(resolver));
+        uint32_t resolved_type_id = info->type_id;
+        switch (static_cast<TypeId>(resolved_type_id)) {
+        case TypeId::NAMED_ENUM:
+          resolved_type_id = static_cast<uint32_t>(TypeId::ENUM);
+          break;
+        case TypeId::TYPED_UNION:
+        case TypeId::NAMED_UNION:
+          resolved_type_id = static_cast<uint32_t>(TypeId::UNION);
+          break;
+        default:
+          break;
+        }
+        ft.type_id = resolved_type_id;
       }
-      ft.type_id = resolved_type_id;
     }
     return ft;
   }
@@ -838,9 +849,9 @@ template <typename T, size_t Index> struct FieldInfoBuilder 
{
       }
     }
 
-    // Override nullable and ref_tracking from field-level metadata
+    // Override nullable and track_ref from field-level metadata
     field_type.nullable = is_nullable;
-    field_type.ref_tracking = track_ref;
+    field_type.track_ref = track_ref;
     field_type.ref_mode = make_ref_mode(is_nullable, track_ref);
 #ifdef FORY_DEBUG
     // DEBUG: Print field info for debugging fingerprint mismatch
@@ -911,9 +922,9 @@ template <typename T, size_t Index> struct FieldInfoBuilder 
{
       }
     }
 
-    // Override nullable and ref_tracking from field-level metadata
+    // Override nullable and track_ref from field-level metadata
     field_type.nullable = is_nullable;
-    field_type.ref_tracking = track_ref;
+    field_type.track_ref = track_ref;
     field_type.ref_mode = make_ref_mode(is_nullable, track_ref);
 #ifdef FORY_DEBUG
     // DEBUG: Print field info for debugging fingerprint mismatch
diff --git a/dart/packages/fory/lib/fory.dart b/dart/packages/fory/lib/fory.dart
index a6493e9ad..61add53da 100644
--- a/dart/packages/fory/lib/fory.dart
+++ b/dart/packages/fory/lib/fory.dart
@@ -38,7 +38,6 @@ export 'src/meta/specs/enum_spec.dart';
 export 'src/fory_impl.dart';
 
 // Constants
-export 'src/const/lang.dart';
 export 'src/const/obj_type.dart';
 
 // User-related
diff --git a/dart/packages/fory/lib/src/const/lang.dart 
b/dart/packages/fory/lib/src/const/lang.dart
deleted file mode 100644
index 024ad1394..000000000
--- a/dart/packages/fory/lib/src/const/lang.dart
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-/// Language supported by fory.
-enum Language{
-  xlang,
-  java,
-  python,
-  cpp,
-  go,
-  javascript,
-  rust,
-  dart;
-
-  static int get peerLangBeginIndex => Language.java.index;
-  static int get peerLangEndIndex => Language.dart.index;
-}
diff --git a/dart/packages/fory/lib/src/serializer/fory_header_serializer.dart 
b/dart/packages/fory/lib/src/serializer/fory_header_serializer.dart
index bc8931090..80bf9e0a3 100644
--- a/dart/packages/fory/lib/src/serializer/fory_header_serializer.dart
+++ b/dart/packages/fory/lib/src/serializer/fory_header_serializer.dart
@@ -19,14 +19,11 @@
 
 import 'package:fory/src/config/fory_config.dart';
 import 'package:fory/src/const/fory_header_const.dart';
-import 'package:fory/src/const/lang.dart';
-import 'package:fory/src/exception/deserialization_exception.dart';
 import 'package:fory/src/memory/byte_reader.dart';
 import 'package:fory/src/memory/byte_writer.dart';
 
 typedef HeaderBrief = ({
   bool isXLang,
-  Language peerLang,
   bool oobEnabled,
 });
 
@@ -47,21 +44,8 @@ final class ForyHeaderSerializer {
     assert (isXLang, 'Now Fory Dart only supports xlang mode');
     bool oobEnabled = (bitmap & ForyHeaderConst.outOfBandFlag) != 0;
     //TODO: oobEnabled unsupported yet.
-    // header: peer_lang
-    int peerLangInd = br.readInt8();
-    if (peerLangInd < Language.peerLangBeginIndex || peerLangInd > 
Language.peerLangEndIndex){
-      throw DeserializationRangeException(peerLangInd, Language.values);
-    }
-    Language.values[peerLangInd];
-    // if (!conf.xlangMode && serialPack.peerLang != Language.DART){
-    //   throw ForyException.deserConflict(
-    //       'PeerLang:${serialPack.peerLang}',
-    //       'XLangMode: false'
-    //   );
-    // }
     return (
       isXLang: isXLang,
-      peerLang: Language.values[peerLangInd],
       oobEnabled: oobEnabled,
     );
   }
@@ -73,7 +57,6 @@ final class ForyHeaderSerializer {
     }
     // callback must be null
     bd.writeInt8(bitmap);
-    bd.writeInt8(Language.dart.index);
     // Next is xWriteRef, handed over to the outside
   }
 }
diff --git a/docs/guide/java/cross-language.md 
b/docs/guide/java/cross-language.md
index c25115b91..e38160f09 100644
--- a/docs/guide/java/cross-language.md
+++ b/docs/guide/java/cross-language.md
@@ -112,7 +112,7 @@ class Person:
     age: pyfory.int32
 
 # Create Fory in xlang mode
-fory = pyfory.Fory(ref_tracking=True)
+fory = pyfory.Fory(ref=True)
 
 # Register with the SAME name as Java
 fory.register_type(Person, typename="example.Person")
diff --git a/docs/guide/rust/cross-language.md 
b/docs/guide/rust/cross-language.md
index 1aecd7b95..4245a56c8 100644
--- a/docs/guide/rust/cross-language.md
+++ b/docs/guide/rust/cross-language.md
@@ -121,7 +121,7 @@ class Person:
     name: str
     age: pyfory.int32
 
-fory = pyfory.Fory(ref_tracking=True)
+fory = pyfory.Fory(ref=True)
 fory.register_type(Person, type_id=100)  # Same ID as Rust
 
 person = fory.deserialize(bytes_from_rust)
diff --git a/docs/guide/xlang/field-reference-tracking.md 
b/docs/guide/xlang/field-reference-tracking.md
index 729f24400..e00d45abd 100644
--- a/docs/guide/xlang/field-reference-tracking.md
+++ b/docs/guide/xlang/field-reference-tracking.md
@@ -43,7 +43,7 @@ Fory fory = Fory.builder()
 ### Python
 
 ```python
-fory = pyfory.Fory(xlang=True, ref_tracking=True)
+fory = pyfory.Fory(xlang=True, ref=True)
 ```
 
 ### Go
@@ -56,7 +56,7 @@ fory := forygo.NewFory(true)  // true enables ref tracking
 
 ```cpp
 auto fory = fory::Fory::create(fory::Config{
-    .ref_tracking = true
+    .track_ref = true
 });
 ```
 
diff --git a/docs/guide/xlang/getting-started.md 
b/docs/guide/xlang/getting-started.md
index 4158eeef6..f8bf4a744 100644
--- a/docs/guide/xlang/getting-started.md
+++ b/docs/guide/xlang/getting-started.md
@@ -95,7 +95,7 @@ import pyfory
 fory = pyfory.Fory()
 
 # Explicit configuration
-fory = pyfory.Fory(ref_tracking=True)
+fory = pyfory.Fory(ref=True)
 ```
 
 ### Go
diff --git a/docs/guide/xlang/serialization.md 
b/docs/guide/xlang/serialization.md
index 8e8439826..791f3c363 100644
--- a/docs/guide/xlang/serialization.md
+++ b/docs/guide/xlang/serialization.md
@@ -458,7 +458,7 @@ class SomeClass:
     f2: Dict[str, str]
     f3: Dict[str, str]
 
-fory = pyfory.Fory(ref_tracking=True)
+fory = pyfory.Fory(ref=True)
 fory.register_type(SomeClass, typename="example.SomeClass")
 obj = SomeClass()
 obj.f2 = {"k1": "v1", "k2": "v2"}
diff --git a/docs/guide/xlang/troubleshooting.md 
b/docs/guide/xlang/troubleshooting.md
index 26a459512..5c0e59a16 100644
--- a/docs/guide/xlang/troubleshooting.md
+++ b/docs/guide/xlang/troubleshooting.md
@@ -187,7 +187,7 @@ Fory fory = Fory.builder()
 
 ```python
 # Python
-fory = pyfory.Fory(ref_tracking=True)
+fory = pyfory.Fory(ref=True)
 ```
 
 ### Duplicate Objects
diff --git a/docs/specification/java_serialization_spec.md 
b/docs/specification/java_serialization_spec.md
index e3093f2b9..5e72d4226 100644
--- a/docs/specification/java_serialization_spec.md
+++ b/docs/specification/java_serialization_spec.md
@@ -53,8 +53,7 @@ bitmap and uses the same flag bits.
 - xlang flag: 1 when serialization uses xlang format, 0 when serialization 
uses Java native format.
 - oob flag: 1 when `BufferCallback` is not null, 0 otherwise.
 
-If xlang flag is set, a one byte language ID is written after the bitmap. In 
Java native mode (xlang
-flag unset), no language byte is written.
+The header is always a single byte; no language ID is written.
 
 ## Reference meta
 
diff --git a/docs/specification/xlang_serialization_spec.md 
b/docs/specification/xlang_serialization_spec.md
index 1256ccb08..670bfe111 100644
--- a/docs/specification/xlang_serialization_spec.md
+++ b/docs/specification/xlang_serialization_spec.md
@@ -257,9 +257,9 @@ The data are serialized using little endian byte order for 
all types.
 Fory header format for xlang serialization:
 
 ```
-|        1 byte bitmap           |   1 byte   |
-+--------------------------------+------------+
-|            flags               |  language  |
+|        1 byte bitmap           |
++--------------------------------+
+|            flags               |
 ```
 
 Detailed byte layout:
@@ -270,7 +270,6 @@ Byte 0:   Bitmap flags
           - Bit 1: xlang flag (0x02)
           - Bit 2: oob flag (0x04)
           - Bits 3-7: reserved
-Byte 1:   Language ID (only present when xlang flag is set)
 ```
 
 - **null flag** (bit 0): 1 when object is null, 0 otherwise. If an object is 
null, only this flag is set.
@@ -279,21 +278,6 @@ Byte 1:   Language ID (only present when xlang flag is set)
 
 All data is encoded in little-endian format.
 
-- **language**: 1 byte indicating the source language. This allows 
deserializers to optimize for specific language characteristics.
-
-### Language IDs
-
-| Language   | ID  |
-| ---------- | --- |
-| XLANG      | 0   |
-| JAVA       | 1   |
-| PYTHON     | 2   |
-| CPP        | 3   |
-| GO         | 4   |
-| JAVASCRIPT | 5   |
-| RUST       | 6   |
-| DART       | 7   |
-
 ## Reference Meta
 
 Reference tracking handles whether the object is null, and whether to track 
reference for the object by writing
@@ -1532,7 +1516,6 @@ This section provides a step-by-step guide for 
implementing Fory xlang serializa
 
 3. **Header Handling**
    - [ ] Write/read bitmap flags (null, xlang, oob)
-   - [ ] Write/read language ID (when xlang flag is set)
 
 ### Phase 2: Basic Type Serializers
 
diff --git a/go/fory/fory.go b/go/fory/fory.go
index fea76a385..83dd60739 100644
--- a/go/fory/fory.go
+++ b/go/fory/fory.go
@@ -37,15 +37,6 @@ var ErrNoSerializer = errors.New("fory: no serializer 
registered for type")
 // Constants
 // ============================================================================
 
-// Language constants for protocol header
-const (
-       LangXLANG uint8 = iota
-       LangJAVA
-       LangPYTHON
-       LangCPP
-       LangGO
-)
-
 // Bitmap flags for protocol header
 const (
        IsNilFlag     = 1 << 0
@@ -767,7 +758,6 @@ func writeHeader(ctx *WriteContext, config Config) {
                bitmap |= OutOfBandFlag
        }
        ctx.buffer.WriteByte_(bitmap)
-       ctx.buffer.WriteByte_(LangGO)
 }
 
 // isNilValue checks if a value is nil, including nil pointers wrapped in any
@@ -809,8 +799,6 @@ func readHeader(ctx *ReadContext) bool {
                return true // is null
        }
 
-       _ = ctx.buffer.ReadByte(err) // language
-
        return false // not null
 }
 
diff --git a/go/fory/struct.go b/go/fory/struct.go
index 18dec4e84..957e4a1d6 100644
--- a/go/fory/struct.go
+++ b/go/fory/struct.go
@@ -1159,7 +1159,7 @@ func (s *structSerializer) computeHash() int32 {
                        FieldID:   field.Meta.TagID,
                        FieldName: SnakeCase(field.Meta.Name),
                        TypeID:    typeId,
-                       // Ref is based on explicit tag annotation only, NOT 
runtime ref_tracking config
+                       // Ref is based on explicit tag annotation only, NOT 
runtime track_ref config
                        // This allows fingerprint to be computed at compile 
time for C++/Rust
                        Ref:      field.Meta.TagRefSet && field.Meta.TagRef,
                        Nullable: nullable,
diff --git a/java/fory-core/src/main/java/org/apache/fory/Fory.java 
b/java/fory-core/src/main/java/org/apache/fory/Fory.java
index a744815f3..9285571dd 100644
--- a/java/fory-core/src/main/java/org/apache/fory/Fory.java
+++ b/java/fory-core/src/main/java/org/apache/fory/Fory.java
@@ -35,7 +35,6 @@ import org.apache.fory.collection.IdentityMap;
 import org.apache.fory.config.CompatibleMode;
 import org.apache.fory.config.Config;
 import org.apache.fory.config.ForyBuilder;
-import org.apache.fory.config.Language;
 import org.apache.fory.config.LongEncoding;
 import org.apache.fory.exception.CopyException;
 import org.apache.fory.exception.DeserializationException;
@@ -76,10 +75,9 @@ import org.apache.fory.util.Preconditions;
 import org.apache.fory.util.StringUtils;
 
 /**
- * Cross-Lang Data layout: 1byte mask: 1-bit null: 0->null, 1->not null 1-bit 
endianness: 0->le,
- * 1->be 1-bit target lang: 0->native, 1->x_lang if x_lang, will write current 
process language as a
- * byte into buffer. 1-bit out-of-band serialization enable flag: 0 -> not 
enabled, 1 -> enabled.
- * other bits reserved.
+ * Cross-language header layout: 1-byte bitmap.
+ *
+ * <p>Bit 0: null flag, Bit 1: xlang flag, Bit 2: out-of-band flag, Bits 3-7 
reserved.
  *
  * <p>serialize/deserialize is user API for root object serialization, 
write/read api is for inner
  * serialization.
@@ -119,7 +117,6 @@ public final class Fory implements BaseFory {
   private final boolean compressInt;
   private final LongEncoding longEncoding;
   private final Generics generics;
-  private Language peerLanguage;
   private BufferCallback bufferCallback;
   private Iterator<MemoryBuffer> outOfBandBuffers;
   private boolean peerOutOfBandEnabled;
@@ -133,7 +130,7 @@ public final class Fory implements BaseFory {
     // Avoid set classLoader in `ForyBuilder`, which won't be clear when
     // `org.apache.fory.ThreadSafeFory.clearClassLoader` is called.
     config = new Config(builder);
-    crossLanguage = config.getLanguage() != Language.JAVA;
+    crossLanguage = config.isXlang();
     this.refTracking = config.trackingRef();
     this.copyRefTracking = config.copyRef();
     this.shareMeta = config.isMetaShareEnabled();
@@ -340,9 +337,9 @@ public final class Fory implements BaseFory {
       }
       depth = 0;
       if (!crossLanguage) {
-        write(buffer, obj);
+        writeRef(buffer, obj);
       } else {
-        xwrite(buffer, obj);
+        xwriteRef(buffer, obj);
       }
       return buffer;
     } catch (Throwable t) {
@@ -410,20 +407,6 @@ public final class Fory implements BaseFory {
     }
   }
 
-  private void write(MemoryBuffer buffer, Object obj) {
-    // reduce caller stack
-    if (!refResolver.writeRefOrNull(buffer, obj)) {
-      TypeInfo typeInfo = classResolver.getOrUpdateTypeInfo(obj.getClass());
-      classResolver.writeTypeInfo(buffer, typeInfo);
-      writeData(buffer, typeInfo, obj);
-    }
-  }
-
-  private void xwrite(MemoryBuffer buffer, Object obj) {
-    buffer.writeByte((byte) Language.JAVA.ordinal());
-    xwriteRef(buffer, obj);
-  }
-
   /** Serialize a nullable referencable object to <code>buffer</code>. */
   public void writeRef(MemoryBuffer buffer, Object obj) {
     if (!refResolver.writeRefOrNull(buffer, obj)) {
@@ -886,11 +869,6 @@ public final class Fory implements BaseFory {
         return null;
       }
       boolean isTargetXLang = (bitmap & isCrossLanguageFlag) == 
isCrossLanguageFlag;
-      if (isTargetXLang) {
-        peerLanguage = Language.values()[buffer.readByte()];
-      } else {
-        peerLanguage = Language.JAVA;
-      }
       peerOutOfBandEnabled = (bitmap & isOutOfBandFlag) == isOutOfBandFlag;
       if (peerOutOfBandEnabled) {
         Preconditions.checkNotNull(
@@ -1382,7 +1360,7 @@ public final class Fory implements BaseFory {
       if (depth > 0) {
         throwDepthSerializationException();
       }
-      write(buffer, obj);
+      writeRef(buffer, obj);
     } catch (Throwable t) {
       throw processSerializationError(t);
     } finally {
diff --git 
a/java/fory-core/src/main/java/org/apache/fory/builder/ObjectCodecOptimizer.java
 
b/java/fory-core/src/main/java/org/apache/fory/builder/ObjectCodecOptimizer.java
index 95c5efe7a..cc3bbf230 100644
--- 
a/java/fory-core/src/main/java/org/apache/fory/builder/ObjectCodecOptimizer.java
+++ 
b/java/fory-core/src/main/java/org/apache/fory/builder/ObjectCodecOptimizer.java
@@ -41,15 +41,15 @@ import org.apache.fory.util.function.SerializableSupplier;
  * <ul>
  *   <li>compiled code for writing every primitive is 22/21 bytes.
  *   <li>compiled code for write/read every boxed primitive is 38/35 bytes.
- *   <li>compiled code for write/read every boxed primitive with ref_tracking 
is 40/81 bytes.
+ *   <li>compiled code for write/read every boxed primitive with track_ref is 
40/81 bytes.
  *   <li>compiled code for write/read every final field on average is 41/82 
bytes.
  *   <li>compiled code for write/read every {@literal List<primitive>} on 
average is 191/201 bytes.
- *   <li>compiled code for write/read every {@literal List<primitive>} with 
boxed ref_tracking on
+ *   <li>compiled code for write/read every {@literal List<primitive>} with 
boxed track_ref on
  *       average is 194/240 bytes.
  *   <li>compiled code for write/read every {@literal List<final>} on average 
is 196/238 bytes.
  *   <li>compiled code for write/read every {@literal Map<boxed, boxed>} on 
average is 270/196
  *       bytes.
- *   <li>compiled code for write/read every {@literal Map<boxed, boxed>} with 
boxed ref_tracking on
+ *   <li>compiled code for write/read every {@literal Map<boxed, boxed>} with 
boxed track_ref on
  *       average is 266/296 bytes.
  *   <li>compiled code for write/read every {@literal Map<final, final>} on 
average is 268/292
  *       bytes.
diff --git a/java/fory-core/src/main/java/org/apache/fory/config/Config.java 
b/java/fory-core/src/main/java/org/apache/fory/config/Config.java
index 148deb213..cc2a6c32d 100644
--- a/java/fory-core/src/main/java/org/apache/fory/config/Config.java
+++ b/java/fory-core/src/main/java/org/apache/fory/config/Config.java
@@ -34,7 +34,7 @@ import org.apache.fory.util.Preconditions;
 @SuppressWarnings({"rawtypes"})
 public class Config implements Serializable {
   private final String name;
-  private final Language language;
+  private final boolean xlang;
   private final boolean trackingRef;
   private final boolean stringRefIgnored;
   private final boolean timeRefIgnored;
@@ -69,7 +69,7 @@ public class Config implements Serializable {
 
   public Config(ForyBuilder builder) {
     name = builder.name;
-    language = builder.language;
+    xlang = builder.xlang;
     trackingRef = builder.trackingRef;
     stringRefIgnored = !trackingRef || builder.stringRefIgnored;
     timeRefIgnored = !trackingRef || builder.timeRefIgnored;
@@ -114,8 +114,8 @@ public class Config implements Serializable {
     return name;
   }
 
-  public Language getLanguage() {
-    return language;
+  public boolean isXlang() {
+    return xlang;
   }
 
   public boolean trackingRef() {
@@ -324,7 +324,7 @@ public class Config implements Serializable {
         && asyncCompilationEnabled == config.asyncCompilationEnabled
         && deserializeNonexistentClass == config.deserializeNonexistentClass
         && scalaOptimizationEnabled == config.scalaOptimizationEnabled
-        && language == config.language
+        && xlang == config.xlang
         && compatibleMode == config.compatibleMode
         && Objects.equals(defaultJDKStreamSerializerType, 
config.defaultJDKStreamSerializerType)
         && longEncoding == config.longEncoding;
@@ -334,7 +334,7 @@ public class Config implements Serializable {
   public int hashCode() {
     return Objects.hash(
         name,
-        language,
+        xlang,
         mapRefLoadFactor,
         trackingRef,
         stringRefIgnored,
diff --git 
a/java/fory-core/src/main/java/org/apache/fory/config/ForyBuilder.java 
b/java/fory-core/src/main/java/org/apache/fory/config/ForyBuilder.java
index aed359c6a..b1c76e1a8 100644
--- a/java/fory-core/src/main/java/org/apache/fory/config/ForyBuilder.java
+++ b/java/fory-core/src/main/java/org/apache/fory/config/ForyBuilder.java
@@ -59,7 +59,7 @@ public final class ForyBuilder {
 
   String name;
   boolean checkClassVersion = false;
-  Language language = Language.JAVA;
+  boolean xlang = false;
   boolean trackingRef = false;
   boolean copyRef = false;
   boolean stringRefIgnored = true;
@@ -93,16 +93,16 @@ public final class ForyBuilder {
   public ForyBuilder() {}
 
   /**
-   * Whether cross-language serialize the object. If you used fory for java 
only, please set
-   * language to {@link Language#JAVA}, which will have much better 
performance.
+   * Whether cross-language serialize the object. If you used fory for java 
only, please keep it in
+   * java mode, which will have much better performance.
    */
   public ForyBuilder withLanguage(Language language) {
-    this.language = language;
+    this.xlang = language == Language.XLANG;
     return this;
   }
 
   public ForyBuilder withXlang(boolean xlang) {
-    this.language = xlang ? Language.XLANG : Language.JAVA;
+    this.xlang = xlang;
     return this;
   }
 
@@ -268,9 +268,7 @@ public final class ForyBuilder {
    * class won't evolve.
    */
   public ForyBuilder withClassVersionCheck(boolean checkClassVersion) {
-    if (language == Language.XLANG
-        && compatibleMode == CompatibleMode.SCHEMA_CONSISTENT
-        && !checkClassVersion) {
+    if (xlang && compatibleMode == CompatibleMode.SCHEMA_CONSISTENT && 
!checkClassVersion) {
       throw new IllegalArgumentException(
           "XLANG Schema consistent mode must enable class version check");
     }
@@ -430,7 +428,7 @@ public final class ForyBuilder {
         classLoader = Fory.class.getClassLoader();
       }
     }
-    if (language != Language.JAVA) {
+    if (xlang) {
       stringRefIgnored = true;
       longEncoding = LongEncoding.VARINT;
       compressInt = true;
@@ -451,7 +449,7 @@ public final class ForyBuilder {
           Serializer.class);
     }
     if (writeNumUtf16BytesForUtf8Encoding == null) {
-      writeNumUtf16BytesForUtf8Encoding = language == Language.JAVA;
+      writeNumUtf16BytesForUtf8Encoding = !xlang;
     }
     if (compatibleMode == CompatibleMode.COMPATIBLE) {
       checkClassVersion = false;
@@ -481,7 +479,7 @@ public final class ForyBuilder {
       if (metaShareEnabled == null) {
         metaShareEnabled = false;
       }
-      if (language != Language.JAVA) {
+      if (xlang) {
         checkClassVersion = true;
       }
     }
diff --git a/java/fory-core/src/main/java/org/apache/fory/config/Language.java 
b/java/fory-core/src/main/java/org/apache/fory/config/Language.java
index 1721cb16b..2e425c35e 100644
--- a/java/fory-core/src/main/java/org/apache/fory/config/Language.java
+++ b/java/fory-core/src/main/java/org/apache/fory/config/Language.java
@@ -23,10 +23,4 @@ package org.apache.fory.config;
 public enum Language {
   XLANG,
   JAVA,
-  PYTHON,
-  CPP,
-  GO,
-  JAVASCRIPT,
-  RUST,
-  DART,
 }
diff --git a/java/fory-core/src/test/java/org/apache/fory/ForyTest.java 
b/java/fory-core/src/test/java/org/apache/fory/ForyTest.java
index 80c5af116..1211aaa98 100644
--- a/java/fory-core/src/test/java/org/apache/fory/ForyTest.java
+++ b/java/fory-core/src/test/java/org/apache/fory/ForyTest.java
@@ -83,7 +83,7 @@ import org.testng.annotations.Test;
 public class ForyTest extends ForyTestBase {
   @DataProvider(name = "languageConfig")
   public static Object[][] languageConfig() {
-    return new Object[][] {{Language.JAVA}, {Language.PYTHON}};
+    return new Object[][] {{Language.JAVA}, {Language.XLANG}};
   }
 
   @Test(dataProvider = "crossLanguageReferenceTrackingConfig")
diff --git 
a/java/fory-core/src/test/java/org/apache/fory/serializer/ArraySerializersTest.java
 
b/java/fory-core/src/test/java/org/apache/fory/serializer/ArraySerializersTest.java
index bd8e93d66..58afa935e 100644
--- 
a/java/fory-core/src/test/java/org/apache/fory/serializer/ArraySerializersTest.java
+++ 
b/java/fory-core/src/test/java/org/apache/fory/serializer/ArraySerializersTest.java
@@ -79,7 +79,7 @@ public class ArraySerializersTest extends ForyTestBase {
       for (Class<?> t : types) {
         f.getSerializer(t);
       }
-      if (f.getConfig().getLanguage() == Language.JAVA) {
+      if (!f.getConfig().isXlang()) {
         f.getSerializer(Character.class);
         f.getSerializer(Character[].class);
         f.getSerializer(Character[][].class);
diff --git a/javascript/packages/fory/lib/fory.ts 
b/javascript/packages/fory/lib/fory.ts
index f5d9e1c6d..88ab42a6f 100644
--- a/javascript/packages/fory/lib/fory.ts
+++ b/javascript/packages/fory/lib/fory.ts
@@ -21,7 +21,7 @@ import TypeResolver from "./typeResolver";
 import { BinaryWriter } from "./writer";
 import { BinaryReader } from "./reader";
 import { ReferenceResolver } from "./referenceResolver";
-import { ConfigFlags, Serializer, Config, Language, Mode, ForyTypeInfoSymbol, 
WithForyClsInfo, TypeId } from "./type";
+import { ConfigFlags, Serializer, Config, Mode, ForyTypeInfoSymbol, 
WithForyClsInfo, TypeId } from "./type";
 import { OwnershipError } from "./error";
 import { InputType, ResultType, StructTypeInfo, TypeInfo } from "./typeInfo";
 import { Gen } from "./gen";
@@ -145,7 +145,6 @@ export default class {
     if (isOutOfBandEnabled) {
       throw new Error("outofband mode is not supported now");
     }
-    this.binaryReader.uint8(); // skip language
     return serializer.readRef();
   }
 
@@ -165,7 +164,6 @@ export default class {
     }
     bitmap |= ConfigFlags.isCrossLanguageFlag;
     this.binaryWriter.uint8(bitmap);
-    this.binaryWriter.uint8(Language.JAVASCRIPT);
     // reserve fixed size
     this.binaryWriter.reserve(serializer.fixedSize);
     // start write
diff --git a/javascript/packages/fory/lib/type.ts 
b/javascript/packages/fory/lib/type.ts
index 448814b66..18ec15e3e 100644
--- a/javascript/packages/fory/lib/type.ts
+++ b/javascript/packages/fory/lib/type.ts
@@ -239,17 +239,6 @@ export interface Config {
   mode: Mode;
 }
 
-export enum Language {
-  XLANG = 0,
-  JAVA = 1,
-  PYTHON = 2,
-  CPP = 3,
-  GO = 4,
-  JAVASCRIPT = 5,
-  RUST = 6,
-  DART = 7,
-}
-
 export interface WithForyClsInfo {
   structTypeInfo: StructTypeInfo;
 }
diff --git a/python/pyfory/__init__.py b/python/pyfory/__init__.py
index 3b4ad2bbc..38538981a 100644
--- a/python/pyfory/__init__.py
+++ b/python/pyfory/__init__.py
@@ -18,13 +18,9 @@
 from pyfory.lib import mmh3
 from pyfory._fory import (
     Fory,
-    Language,
     ThreadSafeFory,
 )
 
-PYTHON = Language.PYTHON
-XLANG = Language.XLANG
-
 try:
     from pyfory.serialization import ENABLE_FORY_CYTHON_SERIALIZATION
 except ImportError:
@@ -128,16 +124,12 @@ __version__ = "0.14.1.dev"
 __all__ = [
     # Core classes
     "Fory",
-    "Language",
     "ThreadSafeFory",
     "TypeInfo",
     "Buffer",
     "DeserializationPolicy",
     # Field metadata
     "field",
-    # Language constants
-    "PYTHON",
-    "XLANG",
     # Type utilities
     "record_class_factory",
     "get_qualified_classname",
diff --git a/python/pyfory/_fory.py b/python/pyfory/_fory.py
index 8b5832063..9d19353bd 100644
--- a/python/pyfory/_fory.py
+++ b/python/pyfory/_fory.py
@@ -15,7 +15,6 @@
 # specific language governing permissions and limitations
 # under the License.
 
-import enum
 import logging
 import os
 from abc import ABC, abstractmethod
@@ -61,17 +60,6 @@ NOT_NULL_STRING_FLAG = NOT_NULL_VALUE_FLAG & 0b11111111 | 
(STRING_TYPE_ID << 8)
 SMALL_STRING_THRESHOLD = 16
 
 
-class Language(enum.Enum):
-    XLANG = 0
-    JAVA = 1
-    PYTHON = 2
-    CPP = 3
-    GO = 4
-    JAVA_SCRIPT = 5
-    RUST = 6
-    DART = 7
-
-
 class BufferObject(ABC):
     """
     Fory binary representation of an object.
@@ -147,10 +135,9 @@ class Fory:
     """
 
     __slots__ = (
-        "language",
-        "is_py",
+        "xlang",
         "compatible",
-        "ref_tracking",
+        "track_ref",
         "ref_resolver",
         "type_resolver",
         "serialization_context",
@@ -161,7 +148,6 @@ class Fory:
         "metastring_resolver",
         "_unsupported_callback",
         "_unsupported_objects",
-        "_peer_language",
         "is_peer_out_of_band_enabled",
         "max_depth",
         "depth",
@@ -179,7 +165,6 @@ class Fory:
         policy: DeserializationPolicy = None,
         field_nullable: bool = False,
         meta_compressor=None,
-        **kwargs,
     ):
         """
         Initialize a Fory serialization instance.
@@ -226,23 +211,16 @@ class Fory:
             >>> # Cross-language mode with schema evolution
             >>> fory = Fory(xlang=True, compatible=True)
         """
-        self.language = Language.XLANG if xlang else Language.PYTHON
-        if kwargs.get("language") is not None:
-            self.language = kwargs.get("language")
-        self.is_py = self.language == Language.PYTHON
-        if kwargs.get("ref_tracking") is not None:
-            ref = kwargs.get("ref_tracking")
-        self.ref_tracking = ref
-        if self.ref_tracking:
+        self.xlang = xlang
+        self.track_ref = ref
+        if self.track_ref:
             self.ref_resolver = MapRefResolver()
         else:
             self.ref_resolver = NoRefResolver()
-        if kwargs.get("require_type_registration") is not None:
-            strict = kwargs.get("require_type_registration")
         self.strict = _ENABLE_TYPE_REGISTRATION_FORCIBLY or strict
         self.policy = policy or DEFAULT_POLICY
         self.compatible = compatible
-        self.field_nullable = field_nullable if self.is_py else False
+        self.field_nullable = field_nullable if not self.xlang else False
         from pyfory.serialization import MetaStringResolver, 
SerializationContext
         from pyfory.registry import TypeResolver
 
@@ -256,7 +234,6 @@ class Fory:
         self._buffers = None
         self._unsupported_callback = None
         self._unsupported_objects = None
-        self._peer_language = None
         self.is_peer_out_of_band_enabled = False
         self.max_depth = max_depth
         self.depth = 0
@@ -485,11 +462,9 @@ class Fory:
         else:
             clear_bit(buffer, mask_index, 0)
 
-        if self.language == Language.XLANG:
+        if self.xlang:
             # set reader as x_lang.
             set_bit(buffer, mask_index, 1)
-            # set writer language.
-            buffer.write_int8(Language.PYTHON.value)
         else:
             # set reader as native.
             clear_bit(buffer, mask_index, 1)
@@ -499,7 +474,7 @@ class Fory:
             clear_bit(buffer, mask_index, 2)
         # Type definitions are now written inline (streaming) instead of 
deferred to end
 
-        if self.language == Language.PYTHON:
+        if not self.xlang:
             self.write_ref(buffer, obj)
         else:
             self.xwrite_ref(buffer, obj)
@@ -618,10 +593,6 @@ class Fory:
         if get_bit(buffer, reader_index, 0):
             return None
         is_target_x_lang = get_bit(buffer, reader_index, 1)
-        if is_target_x_lang:
-            self._peer_language = Language(buffer.read_int8())
-        else:
-            self._peer_language = Language.PYTHON
         self.is_peer_out_of_band_enabled = get_bit(buffer, reader_index, 2)
         if self.is_peer_out_of_band_enabled:
             assert buffers is not None, "buffers shouldn't be null when the 
serialized stream is produced with buffer_callback not null."
@@ -682,7 +653,7 @@ class Fory:
             serializer = self.type_resolver.read_type_info(buffer).serializer
         # Push -1 to read_ref_ids so reference() can pop it and skip reference 
tracking
         # This handles the case where xread_no_ref is called directly without 
xread_ref
-        if self.ref_tracking:
+        if self.track_ref:
             self.ref_resolver.read_ref_ids.append(-1)
         return self._xread_no_ref_internal(buffer, serializer)
 
diff --git a/python/pyfory/_serializer.py b/python/pyfory/_serializer.py
index ca91b9adc..361f2ec14 100644
--- a/python/pyfory/_serializer.py
+++ b/python/pyfory/_serializer.py
@@ -39,7 +39,7 @@ class Serializer(ABC):
     def __init__(self, fory, type_: type):
         self.fory = fory
         self.type_: type = type_
-        self.need_to_write_ref = fory.ref_tracking and not 
is_primitive_type(type_)
+        self.need_to_write_ref = fory.track_ref and not 
is_primitive_type(type_)
 
     def write(self, buffer, value):
         raise NotImplementedError
diff --git a/python/pyfory/collection.pxi b/python/pyfory/collection.pxi
index aa62736c3..df10f1858 100644
--- a/python/pyfory/collection.pxi
+++ b/python/pyfory/collection.pxi
@@ -37,7 +37,6 @@ cdef class CollectionSerializer(Serializer):
     cdef TypeResolver type_resolver
     cdef MapRefResolver ref_resolver
     cdef Serializer elem_serializer
-    cdef c_bool is_py
     cdef int8_t elem_tracking_ref
     cdef elem_type
     cdef TypeInfo elem_type_info
@@ -57,7 +56,6 @@ cdef class CollectionSerializer(Serializer):
             self.elem_tracking_ref = <int8_t> 
(elem_serializer.need_to_write_ref)
             if elem_tracking_ref is not None:
                 self.elem_tracking_ref = <int8_t> (1 if elem_tracking_ref else 
0)
-        self.is_py = fory.is_py
 
     cdef inline pair[int8_t, int64_t] write_header(self, Buffer buffer, value):
         cdef int8_t collect_flag = COLL_DEFAULT_FLAG
@@ -85,7 +83,7 @@ cdef class CollectionSerializer(Serializer):
                     break
         if has_null:
             collect_flag |= COLL_HAS_NULL
-        if self.fory.ref_tracking:
+        if self.fory.track_ref:
             if self.elem_tracking_ref == 1:
                 collect_flag |= COLL_TRACKING_REF
             elif self.elem_tracking_ref == -1:
@@ -109,7 +107,7 @@ cdef class CollectionSerializer(Serializer):
         cdef elem_type = elem_type_info.cls
         cdef MapRefResolver ref_resolver = self.ref_resolver
         cdef TypeResolver type_resolver = self.type_resolver
-        cdef c_bool is_py = self.is_py
+        cdef c_bool is_py = not self.fory.xlang
         cdef serializer = type(elem_type_info.serializer)
         cdef c_bool tracking_ref
         cdef c_bool has_null
@@ -237,7 +235,7 @@ cdef class CollectionSerializer(Serializer):
     cpdef _write_same_type_no_ref(self, Buffer buffer, value, TypeInfo 
typeinfo):
         cdef MapRefResolver ref_resolver = self.ref_resolver
         cdef TypeResolver type_resolver = self.type_resolver
-        if self.is_py:
+        if not self.fory.xlang:
             for s in value:
                 typeinfo.serializer.write(buffer, s)
         else:
@@ -248,7 +246,7 @@ cdef class CollectionSerializer(Serializer):
         cdef MapRefResolver ref_resolver = self.ref_resolver
         cdef TypeResolver type_resolver = self.type_resolver
         self.fory.inc_depth()
-        if self.is_py:
+        if not self.fory.xlang:
             for i in range(len_):
                 obj = typeinfo.serializer.read(buffer)
                 self._add_element(collection_, i, obj)
@@ -259,7 +257,7 @@ cdef class CollectionSerializer(Serializer):
         self.fory.dec_depth()
 
     cpdef _write_same_type_has_null(self, Buffer buffer, value, TypeInfo 
typeinfo):
-        if self.is_py:
+        if not self.fory.xlang:
             for s in value:
                 if s is None:
                     buffer.write_int8(NULL_FLAG)
@@ -277,7 +275,7 @@ cdef class CollectionSerializer(Serializer):
     cpdef _read_same_type_has_null(self, Buffer buffer, int64_t len_, object 
collection_, TypeInfo typeinfo):
         cdef int8_t flag
         self.fory.inc_depth()
-        if self.is_py:
+        if not self.fory.xlang:
             for i in range(len_):
                 flag = buffer.read_int8()
                 if flag == NULL_FLAG:
@@ -300,7 +298,7 @@ cdef class CollectionSerializer(Serializer):
     cpdef _write_same_type_ref(self, Buffer buffer, value, TypeInfo typeinfo):
         cdef MapRefResolver ref_resolver = self.ref_resolver
         cdef TypeResolver type_resolver = self.type_resolver
-        if self.is_py:
+        if not self.fory.xlang:
             for s in value:
                 if not ref_resolver.write_ref_or_null(buffer, s):
                     typeinfo.serializer.write(buffer, s)
@@ -312,7 +310,7 @@ cdef class CollectionSerializer(Serializer):
     cpdef _read_same_type_ref(self, Buffer buffer, int64_t len_, object 
collection_, TypeInfo typeinfo):
         cdef MapRefResolver ref_resolver = self.ref_resolver
         cdef TypeResolver type_resolver = self.type_resolver
-        cdef c_bool is_py = self.is_py
+        cdef c_bool is_py = not self.fory.xlang
         self.fory.inc_depth()
         for i in range(len_):
             ref_id = ref_resolver.try_preserve_ref_id(buffer)
@@ -343,7 +341,7 @@ cdef class ListSerializer(CollectionSerializer):
             return list_
         cdef int8_t collect_flag = buffer.read_int8()
         ref_resolver.reference(list_)
-        cdef c_bool is_py = self.is_py
+        cdef c_bool is_py = not self.fory.xlang
         cdef TypeInfo typeinfo
         cdef uint8_t type_id = 0
         cdef c_bool tracking_ref
@@ -465,7 +463,7 @@ cdef class TupleSerializer(CollectionSerializer):
         if len_ == 0:
             return tuple_
         cdef int8_t collect_flag = buffer.read_int8()
-        cdef c_bool is_py = self.is_py
+        cdef c_bool is_py = not self.fory.xlang
         cdef TypeInfo typeinfo
         cdef uint8_t type_id = 0
         cdef c_bool tracking_ref
@@ -564,7 +562,7 @@ cdef class SetSerializer(CollectionSerializer):
         cdef int32_t ref_id
         cdef TypeInfo typeinfo
         cdef uint8_t type_id = 0
-        cdef c_bool is_py = self.is_py
+        cdef c_bool is_py = not self.fory.xlang
         cdef c_bool tracking_ref
         cdef c_bool has_null
         cdef int8_t head_flag
@@ -708,7 +706,6 @@ cdef class MapSerializer(Serializer):
     cdef MapRefResolver ref_resolver
     cdef Serializer key_serializer
     cdef Serializer value_serializer
-    cdef c_bool is_py
     cdef int8_t key_tracking_ref
     cdef int8_t value_tracking_ref
 
@@ -726,17 +723,16 @@ cdef class MapSerializer(Serializer):
         self.ref_resolver = fory.ref_resolver
         self.key_serializer = key_serializer
         self.value_serializer = value_serializer
-        self.is_py = fory.is_py
         self.key_tracking_ref = 0
         self.value_tracking_ref = 0
         if key_serializer is not None:
             self.key_tracking_ref = <int8_t> (key_serializer.need_to_write_ref)
             if key_tracking_ref is not None:
-                self.key_tracking_ref = <int8_t> (1 if key_tracking_ref and 
fory.ref_tracking else 0)
+                self.key_tracking_ref = <int8_t> (1 if key_tracking_ref and 
fory.track_ref else 0)
         if value_serializer is not None:
             self.value_tracking_ref = <int8_t> 
(value_serializer.need_to_write_ref)
             if value_tracking_ref is not None:
-                self.value_tracking_ref = <int8_t> (1 if value_tracking_ref 
and fory.ref_tracking else 0)
+                self.value_tracking_ref = <int8_t> (1 if value_tracking_ref 
and fory.track_ref else 0)
 
     cpdef inline write(self, Buffer buffer, o):
         cdef dict obj = o
@@ -756,7 +752,7 @@ cdef class MapSerializer(Serializer):
         cdef int32_t chunk_size_offset, chunk_header, chunk_size
         cdef c_bool key_write_ref, value_write_ref
         cdef int has_next = PyDict_Next(obj, &pos, <PyObject **>&key_addr, 
<PyObject **>&value_addr)
-        cdef c_bool is_py = self.is_py
+        cdef c_bool is_py = not self.fory.xlang
         while has_next != 0:
             key = int2obj(key_addr)
             Py_INCREF(key)
@@ -927,7 +923,7 @@ cdef class MapSerializer(Serializer):
         cdef c_bool key_is_declared_type, value_is_declared_type
         cdef type key_serializer_type, value_serializer_type
         cdef int32_t chunk_size
-        cdef c_bool is_py = self.is_py
+        cdef c_bool is_py = not self.fory.xlang
         self.fory.inc_depth()
         while size > 0:
             while True:
diff --git a/python/pyfory/collection.py b/python/pyfory/collection.py
index 1fcef05c9..25c58d9b5 100644
--- a/python/pyfory/collection.py
+++ b/python/pyfory/collection.py
@@ -47,7 +47,6 @@ class CollectionSerializer(Serializer):
         "type_resolver",
         "ref_resolver",
         "elem_serializer",
-        "is_py",
         "elem_tracking_ref",
         "elem_type",
         "elem_type_info",
@@ -68,7 +67,6 @@ class CollectionSerializer(Serializer):
             self.elem_tracking_ref = int(elem_serializer.need_to_write_ref)
             if elem_tracking_ref is not None:
                 self.elem_tracking_ref = 1 if elem_tracking_ref else 0
-        self.is_py = fory.is_py
 
     def write_header(self, buffer, value):
         collect_flag = COLL_DEFAULT_FLAG
@@ -98,7 +96,7 @@ class CollectionSerializer(Serializer):
 
         if has_null:
             collect_flag |= COLL_HAS_NULL
-        if self.fory.ref_tracking:
+        if self.fory.track_ref:
             if self.elem_tracking_ref == 1:
                 collect_flag |= COLL_TRACKING_REF
             elif self.elem_tracking_ref == -1:
@@ -126,7 +124,7 @@ class CollectionSerializer(Serializer):
             self._write_different_types(buffer, value, collect_flag)
 
     def _write_same_type_no_ref(self, buffer, value, typeinfo):
-        if self.is_py:
+        if not self.fory.xlang:
             for s in value:
                 typeinfo.serializer.write(buffer, s)
         else:
@@ -134,7 +132,7 @@ class CollectionSerializer(Serializer):
                 typeinfo.serializer.xwrite(buffer, s)
 
     def _write_same_type_has_null(self, buffer, value, typeinfo):
-        if self.is_py:
+        if not self.fory.xlang:
             for s in value:
                 if s is None:
                     buffer.write_int8(NULL_FLAG)
@@ -150,7 +148,7 @@ class CollectionSerializer(Serializer):
                     typeinfo.serializer.xwrite(buffer, s)
 
     def _write_same_type_ref(self, buffer, value, typeinfo):
-        if self.is_py:
+        if not self.fory.xlang:
             for s in value:
                 if not self.ref_resolver.write_ref_or_null(buffer, s):
                     typeinfo.serializer.write(buffer, s)
@@ -168,7 +166,7 @@ class CollectionSerializer(Serializer):
                 if not self.ref_resolver.write_ref_or_null(buffer, s):
                     typeinfo = self.type_resolver.get_type_info(type(s))
                     self.type_resolver.write_type_info(buffer, typeinfo)
-                    if self.is_py:
+                    if not self.fory.xlang:
                         typeinfo.serializer.write(buffer, s)
                     else:
                         typeinfo.serializer.xwrite(buffer, s)
@@ -177,7 +175,7 @@ class CollectionSerializer(Serializer):
             for s in value:
                 typeinfo = self.type_resolver.get_type_info(type(s))
                 self.type_resolver.write_type_info(buffer, typeinfo)
-                if self.is_py:
+                if not self.fory.xlang:
                     typeinfo.serializer.write(buffer, s)
                 else:
                     typeinfo.serializer.xwrite(buffer, s)
@@ -190,7 +188,7 @@ class CollectionSerializer(Serializer):
                     buffer.write_int8(NOT_NULL_VALUE_FLAG)
                     typeinfo = self.type_resolver.get_type_info(type(s))
                     self.type_resolver.write_type_info(buffer, typeinfo)
-                    if self.is_py:
+                    if not self.fory.xlang:
                         typeinfo.serializer.write(buffer, s)
                     else:
                         typeinfo.serializer.xwrite(buffer, s)
@@ -224,7 +222,7 @@ class CollectionSerializer(Serializer):
 
     def _read_same_type_no_ref(self, buffer, len_, collection_, typeinfo):
         self.fory.inc_depth()
-        if self.is_py:
+        if not self.fory.xlang:
             for _ in range(len_):
                 self._add_element(collection_, 
typeinfo.serializer.read(buffer))
         else:
@@ -237,7 +235,7 @@ class CollectionSerializer(Serializer):
 
     def _read_same_type_has_null(self, buffer, len_, collection_, typeinfo):
         self.fory.inc_depth()
-        if self.is_py:
+        if not self.fory.xlang:
             for _ in range(len_):
                 if buffer.read_int8() == NULL_FLAG:
                     self._add_element(collection_, None)
@@ -261,7 +259,7 @@ class CollectionSerializer(Serializer):
             if ref_id < NOT_NULL_VALUE_FLAG:
                 obj = self.ref_resolver.get_read_object()
             else:
-                if self.is_py:
+                if not self.fory.xlang:
                     obj = typeinfo.serializer.read(buffer)
                 else:
                     obj = typeinfo.serializer.xread(buffer)
@@ -276,7 +274,7 @@ class CollectionSerializer(Serializer):
         if tracking_ref:
             # When ref tracking is enabled, read with ref handling
             for i in range(len_):
-                elem = get_next_element(buffer, self.ref_resolver, 
self.type_resolver, self.is_py)
+                elem = get_next_element(buffer, self.ref_resolver, 
self.type_resolver, not self.fory.xlang)
                 self._add_element(collection_, elem)
         elif not has_null:
             # When ref tracking is disabled and no nulls, read type info 
directly
@@ -284,7 +282,7 @@ class CollectionSerializer(Serializer):
                 typeinfo = self.type_resolver.read_type_info(buffer)
                 if typeinfo is None:
                     elem = None
-                elif self.is_py:
+                elif not self.fory.xlang:
                     elem = typeinfo.serializer.read(buffer)
                 else:
                     elem = self.fory.xread_no_ref(buffer, 
serializer=typeinfo.serializer)
@@ -299,7 +297,7 @@ class CollectionSerializer(Serializer):
                     typeinfo = self.type_resolver.read_type_info(buffer)
                     if typeinfo is None:
                         elem = None
-                    elif self.is_py:
+                    elif not self.fory.xlang:
                         elem = typeinfo.serializer.read(buffer)
                     else:
                         elem = self.fory.xread_no_ref(buffer, 
serializer=typeinfo.serializer)
@@ -409,11 +407,11 @@ class MapSerializer(Serializer):
         if key_serializer is not None:
             self.key_tracking_ref = bool(key_serializer.need_to_write_ref)
             if key_tracking_ref is not None:
-                self.key_tracking_ref = bool(key_tracking_ref) and 
fory.ref_tracking
+                self.key_tracking_ref = bool(key_tracking_ref) and 
fory.track_ref
         if value_serializer is not None:
             self.value_tracking_ref = bool(value_serializer.need_to_write_ref)
             if value_tracking_ref is not None:
-                self.value_tracking_ref = bool(value_tracking_ref) and 
fory.ref_tracking
+                self.value_tracking_ref = bool(value_tracking_ref) and 
fory.track_ref
 
     def write(self, buffer, o):
         obj = o
@@ -430,7 +428,7 @@ class MapSerializer(Serializer):
         items_iter = iter(obj.items())
         key, value = next(items_iter)
         has_next = True
-        write_ref = fory.write_ref if self.fory.is_py else fory.xwrite_ref
+        write_ref = fory.write_ref if not self.fory.xlang else fory.xwrite_ref
         while has_next:
             while True:
                 if key is not None:
@@ -541,7 +539,7 @@ class MapSerializer(Serializer):
         if size != 0:
             chunk_header = buffer.read_uint8()
         key_serializer, value_serializer = self.key_serializer, 
self.value_serializer
-        read_ref = fory.read_ref if self.fory.is_py else fory.xread_ref
+        read_ref = fory.read_ref if not self.fory.xlang else fory.xread_ref
         fory.inc_depth()
         while size > 0:
             while True:
@@ -626,19 +624,19 @@ class MapSerializer(Serializer):
         return map_
 
     def _write_obj(self, serializer, buffer, obj):
-        if self.fory.is_py:
+        if not self.fory.xlang:
             serializer.write(buffer, obj)
         else:
             serializer.xwrite(buffer, obj)
 
     def _read_obj(self, serializer, buffer):
-        if self.fory.is_py:
+        if not self.fory.xlang:
             return serializer.read(buffer)
         else:
             return serializer.xread(buffer)
 
     def _read_obj_no_ref(self, serializer, buffer):
-        if self.fory.is_py:
+        if not self.fory.xlang:
             return serializer.read(buffer)
         return self.fory.xread_no_ref(buffer, serializer=serializer)
 
diff --git a/python/pyfory/field.py b/python/pyfory/field.py
index 52ea70fa1..fd67b740c 100644
--- a/python/pyfory/field.py
+++ b/python/pyfory/field.py
@@ -106,7 +106,7 @@ def field(
         ref: Whether to enable reference tracking for this field.
             - False (default): No tracking, skip IdentityMap overhead
             - True: Track references (handles circular refs, shared objects)
-            Note: If Fory(ref_tracking=False), all fields use ref=False
+            Note: If Fory(ref=False), all fields use ref=False
             regardless of this setting.
 
         ignore: Whether to ignore this field during serialization.
diff --git a/python/pyfory/meta/typedef.py b/python/pyfory/meta/typedef.py
index ee822392e..e7099e864 100644
--- a/python/pyfory/meta/typedef.py
+++ b/python/pyfory/meta/typedef.py
@@ -177,7 +177,7 @@ class TypeDef:
         return DataClassSerializer(
             fory,
             self.cls,
-            xlang=not fory.is_py,
+            xlang=fory.xlang,
             field_names=field_names,
             serializers=self.create_fields_serializer(resolver, field_names),
             nullable_fields=nullable_fields,
@@ -465,7 +465,7 @@ def build_field_infos(type_resolver, cls):
     nullable_map = {}
     visitor = StructTypeIdVisitor(type_resolver.fory, cls)
     field_nullable = type_resolver.fory.field_nullable
-    global_ref_tracking = type_resolver.fory.ref_tracking
+    global_ref_tracking = type_resolver.fory.track_ref
 
     for field_name in field_names:
         field_type_hint = type_hints.get(field_name, typing.Any)
@@ -483,21 +483,21 @@ def build_field_infos(type_resolver, cls):
         else:
             # For xlang mode: only Optional[T] types are nullable by default
             # For native mode: all reference types are nullable by default
-            if type_resolver.fory.is_py:
+            if not type_resolver.fory.xlang:
                 is_nullable = is_optional or not 
is_primitive_type(unwrapped_type)
             else:
                 # For xlang: only Optional[T] types are nullable
                 is_nullable = is_optional
 
-        # Determine ref tracking: field.ref AND global ref_tracking
+        # Determine ref tracking: field.ref AND global track_ref
         # For xlang mode: ref tracking defaults to false unless explicitly 
annotated
         # This matches Java's behavior in TypeResolver.getFieldDescriptors()
         if fory_meta is not None:
             is_tracking_ref = fory_meta.ref and global_ref_tracking
         else:
             # In xlang mode, default to false (matches Java's xlang behavior)
-            # In native mode, use global ref_tracking setting
-            is_tracking_ref = global_ref_tracking if type_resolver.fory.is_py 
else False
+            # In native mode, use global track_ref setting
+            is_tracking_ref = global_ref_tracking if not 
type_resolver.fory.xlang else False
 
         # Get tag_id from metadata (-1 if not specified)
         tag_id = fory_meta.id if fory_meta is not None else -1
@@ -656,7 +656,7 @@ def build_field_type(type_resolver, field_name: str, 
type_hint, visitor, is_null
 
 
 def build_field_type_from_type_ids(type_resolver, field_name: str, type_ids, 
visitor, is_nullable=False, type_hint=None):
-    tracking_ref = type_resolver.fory.ref_tracking
+    tracking_ref = type_resolver.fory.track_ref
     type_id = type_ids[0]
     if type_id is None:
         type_id = TypeId.UNKNOWN
diff --git a/python/pyfory/registry.py b/python/pyfory/registry.py
index 0f6c70ff9..3d2394002 100644
--- a/python/pyfory/registry.py
+++ b/python/pyfory/registry.py
@@ -28,7 +28,6 @@ from typing import TypeVar, Union
 from enum import Enum
 
 from pyfory import ENABLE_FORY_CYTHON_SERIALIZATION
-from pyfory import Language
 from pyfory.error import TypeUnregisteredError
 
 from pyfory.serializer import (
@@ -197,7 +196,6 @@ class TypeResolver:
         "meta_compressor",
         "require_registration",
         "metastring_resolver",
-        "language",
         "_type_id_to_type_info",
         "_user_type_id_to_type_info",
         "_used_user_type_ids",
@@ -210,7 +208,6 @@ class TypeResolver:
     def __init__(self, fory, meta_share=False, meta_compressor=None):
         self.fory = fory
         self.metastring_resolver = fory.metastring_resolver
-        self.language = fory.language
         self.require_registration = fory.strict
         self._metastr_to_str = dict()
         self._metastr_to_type = dict()
@@ -239,7 +236,7 @@ class TypeResolver:
 
     def initialize(self):
         self._initialize_common()
-        if self.fory.language == Language.PYTHON:
+        if not self.fory.xlang:
             self._initialize_py()
         else:
             self._initialize_xlang()
@@ -452,7 +449,7 @@ class TypeResolver:
             raise TypeError(f"type name {typename} and id {type_id} should not 
be set at the same time")
         if cls in self._types_info:
             raise TypeError(f"{cls} registered already")
-        register_type = self._register_xtype if self.fory.language == 
Language.XLANG else self._register_pytype
+        register_type = self._register_xtype if self.fory.xlang else 
self._register_pytype
         return register_type(
             cls,
             type_id=type_id,
@@ -587,7 +584,7 @@ class TypeResolver:
                 if user_type_id not in self._user_type_id_to_type_info or not 
internal:
                     self._user_type_id_to_type_info[user_type_id] = typeinfo
                 self._used_user_type_ids.add(user_type_id)
-            elif self.language == Language.PYTHON or not 
TypeId.is_namespaced_type(type_id):
+            elif not self.fory.xlang or not TypeId.is_namespaced_type(type_id):
                 if type_id not in self._type_id_to_type_info or not internal:
                     self._type_id_to_type_info[type_id] = typeinfo
         self._types_info[cls] = typeinfo
@@ -610,7 +607,7 @@ class TypeResolver:
         if cls not in self._types_info:
             raise TypeUnregisteredError(f"{cls} not registered")
         typeinfo = self._types_info[cls]
-        if self.fory.language == Language.PYTHON:
+        if not self.fory.xlang:
             typeinfo.serializer = serializer
             return
         prev_type_id = typeinfo.type_id
@@ -653,7 +650,7 @@ class TypeResolver:
         logger.info("Type %s not registered", cls)
         serializer = self._create_serializer(cls)
         type_id = None
-        if self.language == Language.PYTHON:
+        if not self.fory.xlang:
             if isinstance(serializer, EnumSerializer):
                 type_id = TypeId.NAMED_ENUM
             elif isinstance(serializer, (ObjectSerializer, 
StatefulSerializer)):
@@ -683,7 +680,7 @@ class TypeResolver:
             # Set a stub serializer FIRST to break recursion for 
self-referencing types.
             # get_type_info() only calls _set_type_info when serializer is 
None,
             # so setting stub first prevents re-entry for circular type 
references.
-            typeinfo.serializer = DataClassStubSerializer(self.fory, 
typeinfo.cls, xlang=not self.fory.is_py)
+            typeinfo.serializer = DataClassStubSerializer(self.fory, 
typeinfo.cls, xlang=self.fory.xlang)
 
             if self.meta_share:
                 type_def = encode_typedef(self, typeinfo.cls)
@@ -691,9 +688,9 @@ class TypeResolver:
                     typeinfo.serializer = type_def.create_serializer(self)
                     typeinfo.type_def = type_def
                 else:
-                    typeinfo.serializer = DataClassSerializer(self.fory, 
typeinfo.cls, xlang=not self.fory.is_py)
+                    typeinfo.serializer = DataClassSerializer(self.fory, 
typeinfo.cls, xlang=self.fory.xlang)
             else:
-                typeinfo.serializer = DataClassSerializer(self.fory, 
typeinfo.cls, xlang=not self.fory.is_py)
+                typeinfo.serializer = DataClassSerializer(self.fory, 
typeinfo.cls, xlang=self.fory.xlang)
         else:
             typeinfo.serializer = self._create_serializer(typeinfo.cls)
 
@@ -730,7 +727,7 @@ class TypeResolver:
                 # lazy create serializer to handle nested struct fields.
                 from pyfory.struct import DataClassStubSerializer
 
-                serializer = DataClassStubSerializer(self.fory, cls, xlang=not 
self.fory.is_py)
+                serializer = DataClassStubSerializer(self.fory, cls, 
xlang=self.fory.xlang)
             elif issubclass(cls, enum.Enum):
                 serializer = EnumSerializer(self.fory, cls)
             elif ("builtin_function_or_method" in str(cls) or 
"cython_function_or_method" in str(cls)) and "<locals>" not in str(cls):
diff --git a/python/pyfory/serialization.pyx b/python/pyfory/serialization.pyx
index 006f46523..154c4cc8f 100644
--- a/python/pyfory/serialization.pyx
+++ b/python/pyfory/serialization.pyx
@@ -29,7 +29,6 @@ from typing import TypeVar, Union, Iterable
 
 from pyfory.buffer import get_bit, set_bit, clear_bit
 from pyfory import _fory as fmod
-from pyfory._fory import Language
 from pyfory._fory import _ENABLE_TYPE_REGISTRATION_FORCIBLY
 from pyfory.lib import mmh3
 from pyfory.meta.metastring import Encoding
@@ -101,7 +100,7 @@ cdef class MapRefResolver:
     efficient serialization of object graphs with duplicate references and 
prevents
     infinite recursion with circular references.
 
-    When ref_tracking is enabled, duplicate object references are serialized 
only once,
+    When track_ref is enabled, duplicate object references are serialized only 
once,
     with subsequent references storing only the reference ID. During 
deserialization,
     the resolver maintains a mapping to reconstruct the exact same object 
graph structure.
 
@@ -115,18 +114,18 @@ cdef class MapRefResolver:
     cdef vector[PyObject *] read_objects
     cdef vector[int32_t] read_ref_ids
     cdef object read_object
-    cdef c_bool ref_tracking
+    cdef c_bool track_ref
 
     def __cinit__(self, c_bool ref):
         self.read_object = None
-        self.ref_tracking = ref
+        self.track_ref = ref
 
     # Special methods of extension types must be declared with def, not cdef.
     def __dealloc__(self):
         self.reset()
 
     cpdef inline c_bool write_ref_or_null(self, Buffer buffer, obj):
-        if not self.ref_tracking:
+        if not self.track_ref:
             if obj is None:
                 buffer.write_int8(NULL_FLAG)
                 return True
@@ -155,7 +154,7 @@ cdef class MapRefResolver:
 
     cpdef inline int8_t read_ref_or_null(self, Buffer buffer):
         cdef int8_t head_flag = buffer.read_int8()
-        if not self.ref_tracking:
+        if not self.track_ref:
             return head_flag
         cdef int32_t ref_id
         cdef PyObject * obj
@@ -172,7 +171,7 @@ cdef class MapRefResolver:
             return head_flag
 
     cpdef inline int32_t preserve_ref_id(self):
-        if not self.ref_tracking:
+        if not self.track_ref:
             return -1
         next_read_ref_id = self.read_objects.size()
         self.read_objects.push_back(NULL)
@@ -180,7 +179,7 @@ cdef class MapRefResolver:
         return next_read_ref_id
 
     cpdef inline int32_t try_preserve_ref_id(self, Buffer buffer):
-        if not self.ref_tracking:
+        if not self.track_ref:
             # `NOT_NULL_VALUE_FLAG` can be used as stub reference id because 
we use
             # `ref_id >= NOT_NULL_VALUE_FLAG` to read data.
             return buffer.read_int8()
@@ -213,7 +212,7 @@ cdef class MapRefResolver:
         return self.read_ref_ids[length - 1]
 
     cpdef inline reference(self, obj):
-        if not self.ref_tracking:
+        if not self.track_ref:
             return
         cdef int32_t ref_id = self.read_ref_ids.back()
         self.read_ref_ids.pop_back()
@@ -228,7 +227,7 @@ cdef class MapRefResolver:
         self.read_objects[ref_id] = <PyObject *> obj
 
     cpdef inline get_read_object(self, id_=None):
-        if not self.ref_tracking:
+        if not self.track_ref:
             return None
         if id_ is None:
             return self.read_object
@@ -239,7 +238,7 @@ cdef class MapRefResolver:
         return <object> obj
 
     cpdef inline set_read_object(self, int32_t ref_id, obj):
-        if not self.ref_tracking:
+        if not self.track_ref:
             return
         if ref_id >= 0:
             need_inc = self.read_objects[ref_id] == NULL
@@ -258,7 +257,7 @@ cdef class MapRefResolver:
         self.written_objects.clear()
 
     cpdef inline reset_read(self):
-        if not self.ref_tracking:
+        if not self.track_ref:
             return
         for item in self.read_objects:
             Py_XDECREF(item)
@@ -627,7 +626,7 @@ cdef class TypeResolver:
         else:
             if type_id >= self._c_registered_id_to_type_info.size():
                 self._c_registered_id_to_type_info.resize(type_id * 2, NULL)
-            if type_id > 0 and (self.fory.language == Language.PYTHON or not 
is_namespaced_type(<TypeId>type_id)):
+            if type_id > 0 and (not self.fory.xlang or not 
is_namespaced_type(<TypeId>type_id)):
                 self._c_registered_id_to_type_info[type_id] = <PyObject *> 
typeinfo
         self._c_types_info[<uintptr_t> <PyObject *> typeinfo.cls] = <PyObject 
*> typeinfo
         # Resize if load factor >= 0.4 (using integer arithmetic: 
size/capacity >= 4/10)
@@ -1020,10 +1019,9 @@ cdef class Fory:
     See Also:
         ThreadSafeFory: Thread-safe wrapper for concurrent usage
     """
-    cdef readonly object language
-    cdef readonly c_bool ref_tracking
+    cdef readonly c_bool xlang
+    cdef readonly c_bool track_ref
     cdef readonly c_bool strict
-    cdef readonly c_bool is_py
     cdef readonly c_bool compatible
     cdef readonly c_bool field_nullable
     cdef readonly object policy
@@ -1036,7 +1034,6 @@ cdef class Fory:
     cdef object _buffers  # iterator
     cdef object _unsupported_callback
     cdef object _unsupported_objects  # iterator
-    cdef object _peer_language
     cdef public bint is_peer_out_of_band_enabled
     cdef int32_t max_depth
     cdef int32_t depth
@@ -1051,7 +1048,6 @@ cdef class Fory:
             max_depth: int = 50,
             field_nullable: bool = False,
             meta_compressor=None,
-            **kwargs,
     ):
         """
         Initialize a Fory serialization instance.
@@ -1098,23 +1094,16 @@ cdef class Fory:
             >>> # Cross-language mode with schema evolution
             >>> fory = Fory(xlang=True, compatible=True)
         """
-        self.language = Language.XLANG if xlang else Language.PYTHON
-        if kwargs.get("language") is not None:
-            self.language = kwargs.get("language")
-        if kwargs.get("ref_tracking") is not None:
-            ref = kwargs.get("ref_tracking")
-        if kwargs.get("require_type_registration") is not None:
-            strict = kwargs.get("require_type_registration")
+        self.xlang = xlang
         if _ENABLE_TYPE_REGISTRATION_FORCIBLY or strict:
             self.strict = True
         else:
             self.strict = False
         self.policy = policy or DEFAULT_POLICY
         self.compatible = compatible
-        self.ref_tracking = ref
+        self.track_ref = ref
         self.ref_resolver = MapRefResolver(ref)
-        self.is_py = self.language == Language.PYTHON
-        self.field_nullable = field_nullable if self.is_py else False
+        self.field_nullable = field_nullable if not self.xlang else False
         self.metastring_resolver = MetaStringResolver()
         self.type_resolver = TypeResolver(self, meta_share=compatible, 
meta_compressor=meta_compressor)
         self.serialization_context = SerializationContext(fory=self, 
scoped_meta_share_enabled=compatible)
@@ -1124,7 +1113,6 @@ cdef class Fory:
         self._buffers = None
         self._unsupported_callback = None
         self._unsupported_objects = None
-        self._peer_language = None
         self.is_peer_out_of_band_enabled = False
         self.depth = 0
         self.max_depth = max_depth
@@ -1327,11 +1315,9 @@ cdef class Fory:
         else:
             clear_bit(buffer, mask_index, 0)
 
-        if self.language == Language.XLANG:
+        if self.xlang:
             # set reader as x_lang.
             set_bit(buffer, mask_index, 1)
-            # set writer language.
-            buffer.write_int8(Language.PYTHON.value)
         else:
             # set reader as native.
             clear_bit(buffer, mask_index, 1)
@@ -1340,7 +1326,7 @@ cdef class Fory:
         else:
             clear_bit(buffer, mask_index, 2)
         cdef int32_t start_offset
-        if self.language == Language.PYTHON:
+        if not self.xlang:
             self.write_ref(buffer, obj)
         else:
             self.xwrite_ref(buffer, obj)
@@ -1468,10 +1454,6 @@ cdef class Fory:
         if get_bit(buffer, reader_index, 0):
             return None
         cdef c_bool is_target_x_lang = get_bit(buffer, reader_index, 1)
-        if is_target_x_lang:
-            self._peer_language = Language(buffer.read_int8())
-        else:
-            self._peer_language = Language.PYTHON
         self.is_peer_out_of_band_enabled = get_bit(buffer, reader_index, 2)
         if self.is_peer_out_of_band_enabled:
             assert buffers is not None, (
@@ -1558,7 +1540,7 @@ cdef class Fory:
             serializer = self.type_resolver.read_type_info(buffer).serializer
         # Push -1 to read_ref_ids so reference() can pop it and skip reference 
tracking
         # This handles the case where xread_no_ref is called directly without 
xread_ref
-        if self.ref_resolver.ref_tracking:
+        if self.ref_resolver.track_ref:
             self.ref_resolver.read_ref_ids.push_back(-1)
         return self._xread_no_ref_internal(buffer, serializer)
 
@@ -1841,7 +1823,7 @@ cdef class Serializer:
     def __init__(self, fory, type_: Union[type, TypeVar]):
         self.fory = fory
         self.type_ = type_
-        self.need_to_write_ref = fory.ref_tracking and not 
is_primitive_type(type_)
+        self.need_to_write_ref = fory.track_ref and not 
is_primitive_type(type_)
 
     cpdef write(self, Buffer buffer, value):
         raise NotImplementedError(f"write method not implemented in 
{type(self)}")
diff --git a/python/pyfory/serializer.py b/python/pyfory/serializer.py
index fb64d3881..00b6a44ab 100644
--- a/python/pyfory/serializer.py
+++ b/python/pyfory/serializer.py
@@ -865,7 +865,7 @@ class TypeSerializer(Serializer):
 
     def _serialize_local_class(self, buffer, cls):
         """Serialize a local class by capturing its creation context."""
-        assert self.fory.ref_tracking, "Reference tracking must be enabled for 
local classes serialization"
+        assert self.fory.track_ref, "Reference tracking must be enabled for 
local classes serialization"
         # Basic class information
         module = cls.__module__
         qualname = cls.__qualname__
@@ -907,7 +907,7 @@ class TypeSerializer(Serializer):
     def _deserialize_local_class(self, buffer):
         """Deserialize a local class by recreating it with the captured 
context."""
         fory = self.fory
-        assert fory.ref_tracking, "Reference tracking must be enabled for 
local classes deserialization"
+        assert fory.track_ref, "Reference tracking must be enabled for local 
classes deserialization"
         # Read basic class information
         module = buffer.read_string()
         qualname = buffer.read_string()
diff --git a/python/pyfory/struct.py b/python/pyfory/struct.py
index 21a622318..ab45111a8 100644
--- a/python/pyfory/struct.py
+++ b/python/pyfory/struct.py
@@ -109,7 +109,7 @@ class FieldInfo:
     dynamic: bool  # Whether type info is written for this field
 
     # Runtime flags (combines field metadata with global Fory config)
-    runtime_ref_tracking: bool  # Actual ref tracking: field.ref AND 
fory.ref_tracking
+    runtime_ref_tracking: bool  # Actual ref tracking: field.ref AND 
fory.track_ref
 
     # Derived info
     type_id: int  # Fory TypeId
@@ -158,7 +158,7 @@ def _default_field_meta(type_hint: type, field_nullable: 
bool = False, xlang: bo
         nullable = is_optional or not is_primitive_type(unwrapped_type) or 
field_nullable
     # Default ref=False to preserve original serialization behavior where 
non-nullable
     # fields use xwrite_no_ref. Users can explicitly set ref=True in 
pyfory.field()
-    # to enable per-field ref tracking when fory.ref_tracking is enabled.
+    # to enable per-field ref tracking when fory.track_ref is enabled.
     # Default dynamic=None for auto-detection based on type and mode
     return ForyFieldMeta(id=-1, nullable=nullable, ref=False, ignore=False, 
dynamic=None)
 
@@ -226,7 +226,7 @@ def _extract_field_infos(
     # Build FieldInfo list
     field_infos: List[FieldInfo] = []
     visitor = StructFieldSerializerVisitor(fory)
-    global_ref_tracking = fory.ref_tracking
+    global_ref_tracking = fory.track_ref
 
     for index, (field_name, dc_field) in enumerate(active_fields):
         meta = field_metas[field_name]
@@ -404,7 +404,7 @@ class DataClassSerializer(Serializer):
             if _ENABLE_FORY_PYTHON_JIT:
                 self.xwrite = self._generated_xwrite_method
                 self.xread = self._generated_xread_method
-            if self.fory.is_py:
+            if not self.fory.xlang:
                 logger.warning(
                     "Type of class %s shouldn't be serialized using 
cross-language serializer",
                     clz,
diff --git a/python/pyfory/tests/test_cross_language.py 
b/python/pyfory/tests/test_cross_language.py
index b093cad71..14565c581 100644
--- a/python/pyfory/tests/test_cross_language.py
+++ b/python/pyfory/tests/test_cross_language.py
@@ -656,7 +656,7 @@ def test_register_serializer(data_file_path):
     fory.serialize(new_obj, buffer=new_buf)
     bytes1 = fory.serialize(new_obj)
     assert len(bytes1) == len(data_bytes), (bytes1, data_bytes)
-    # header can be different to embed writer info like language
+    # header can differ across writers
     assert bytes1[8:] == data_bytes[8:]
     assert fory.deserialize(fory.serialize(new_obj)) == new_obj, new_obj
     print(f"test_register_serializer: {new_obj}")
diff --git a/python/pyfory/tests/test_method.py 
b/python/pyfory/tests/test_method.py
index cb3785751..346407ee0 100644
--- a/python/pyfory/tests/test_method.py
+++ b/python/pyfory/tests/test_method.py
@@ -350,7 +350,7 @@ def test_global_methods_without_ref_tracking():
     """Test serialization of global class methods without reference 
tracking."""
     fory = pyfory.Fory(strict=False, ref=False)
 
-    # Global classes should work even without ref_tracking
+    # Global classes should work even without track_ref
     method = GlobalTestClass.class_method
     serialized = fory.serialize(method)
     deserialized = fory.deserialize(serialized)
diff --git a/python/pyfory/tests/test_serializer.py 
b/python/pyfory/tests/test_serializer.py
index e4b4d643a..88fdccce3 100644
--- a/python/pyfory/tests/test_serializer.py
+++ b/python/pyfory/tests/test_serializer.py
@@ -34,7 +34,7 @@ import pytest
 
 import pyfory
 from pyfory.buffer import Buffer
-from pyfory import Fory, Language, serialization, EnumSerializer
+from pyfory import Fory, serialization, EnumSerializer
 from pyfory.serializer import (
     TimestampSerializer,
     DateSerializer,
@@ -126,16 +126,16 @@ def test_big_chunk_dict(track_ref):
     assert ser_de(fory, dict0) == dict0
 
 
[email protected]("language", [Language.XLANG, Language.PYTHON])
-def test_basic_serializer(language):
-    fory = Fory(language=language, ref=True)
[email protected]("xlang", [True, False])
+def test_basic_serializer(xlang):
+    fory = Fory(xlang=xlang, ref=True)
     typeinfo = fory.type_resolver.get_type_info(datetime.datetime)
     assert isinstance(typeinfo.serializer, (TimestampSerializer, 
serialization.TimestampSerializer))
-    if language == Language.XLANG:
+    if xlang:
         assert typeinfo.type_id == TypeId.TIMESTAMP
     typeinfo = fory.type_resolver.get_type_info(datetime.date)
     assert isinstance(typeinfo.serializer, (DateSerializer, 
serialization.DateSerializer))
-    if language == Language.XLANG:
+    if xlang:
         assert typeinfo.type_id == TypeId.DATE
     assert ser_de(fory, True) is True
     assert ser_de(fory, False) is False
@@ -164,14 +164,14 @@ def test_basic_serializer(language):
     assert ser_de(fory, set_) == set_
 
 
[email protected]("language", [Language.XLANG, Language.PYTHON])
-def test_ref_tracking(language):
-    fory = Fory(language=language, ref=True)
[email protected]("xlang", [True, False])
+def test_ref_tracking(xlang):
+    fory = Fory(xlang=xlang, ref=True)
 
     # Circular reference test - only works for Python language mode
     # XLANG mode doesn't support true circular references during 
deserialization
     # because the object must be registered after it's fully constructed
-    if language == Language.PYTHON:
+    if not xlang:
         simple_list = []
         simple_list.append(simple_list)
         new_simple_list = ser_de(fory, simple_list)
@@ -191,7 +191,7 @@ def test_ref_tracking(language):
         "dict2_1": dict2,
     }
     # Circular reference in dict3 - only works for Python language mode
-    if language == Language.PYTHON:
+    if not xlang:
         dict3["dict3_0"] = dict3
         dict3["dict3_1"] = dict3
     new_dict3 = ser_de(fory, dict3)
@@ -201,16 +201,16 @@ def test_ref_tracking(language):
     assert new_dict3["dict1_0"] is new_dict3["dict1_1"]
     assert new_dict3["dict2_0"] == dict2
     assert new_dict3["dict2_0"] is new_dict3["dict2_1"]
-    if language == Language.PYTHON:
+    if not xlang:
         assert new_dict3["dict3_0"] is new_dict3
         assert new_dict3["dict3_0"] is new_dict3["dict3_0"]
 
 
[email protected]("language", [Language.PYTHON, Language.XLANG])
-def test_tmp_ref(language):
[email protected]("xlang", [False, True])
+def test_tmp_ref(xlang):
     # FIXME this can't simulate the case where new objects are allocated on 
memory
     #  address of released tmp object.
-    fory = Fory(language=language, ref=True)
+    fory = Fory(xlang=xlang, ref=True)
     buffer = Buffer.allocate(128)
     writer_index = buffer.get_writer_index()
     x = 1
@@ -230,11 +230,11 @@ def test_tmp_ref(language):
     assert l2 is not l3
 
 
[email protected]("language", [Language.PYTHON, Language.XLANG])
-def test_multiple_ref(language):
[email protected]("xlang", [False, True])
+def test_multiple_ref(xlang):
     # FIXME this can't simulate the case where new objects are allocated on 
memory
     #  address of released tmp object.
-    fory = Fory(language=language, ref=True)
+    fory = Fory(xlang=xlang, ref=True)
     buffer = Buffer.allocate(128)
     for i in range(1000):
         fory.serialize([], buffer)
@@ -254,12 +254,10 @@ class RefTestClass2:
         self.f1 = f1
 
 
[email protected]("language", [Language.PYTHON])
-def test_ref_cleanup(language):
+def test_ref_cleanup():
     # FIXME this can't simulate the case where new objects are allocated on 
memory
     #  address of released tmp object.
-    fory = Fory(language=language, ref=True, strict=False)
-    # TODO support Language.XLANG, current unpickler will error for xlang,
+    fory = Fory(xlang=False, ref=True, strict=False)
     o1 = RefTestClass1()
     o2 = RefTestClass2(f1=o1)
     pickle.loads(pickle.dumps(o2))
@@ -273,9 +271,9 @@ def test_ref_cleanup(language):
     fory.deserialize(data)
 
 
[email protected]("language", [Language.XLANG, Language.PYTHON])
-def test_array_serializer(language):
-    fory = Fory(language=language, ref=True, strict=False)
[email protected]("xlang", [True, False])
+def test_array_serializer(xlang):
+    fory = Fory(xlang=xlang, ref=True, strict=False)
     for typecode in PyArraySerializer.typecode_dict.keys():
         arr = array.array(typecode, list(range(10)))
         new_arr = ser_de(fory, arr)
diff --git a/python/pyfory/tests/test_struct.py 
b/python/pyfory/tests/test_struct.py
index 925f39469..265307111 100644
--- a/python/pyfory/tests/test_struct.py
+++ b/python/pyfory/tests/test_struct.py
@@ -209,7 +209,7 @@ def test_data_class_serializer_xlang():
     assert type(fory.type_resolver.get_serializer(DataClassObject)) is 
pyfory.DataClassSerializer
     # Ensure it's using xlang mode indirectly, by checking no JIT methods if 
possible,
     # or by ensuring it was registered with _register_xtype which now uses 
DataClassSerializer(xlang=True)
-    # For now, the registration path check is implicit via Language.XLANG 
usage.
+    # For now, the registration path check is implicit via xlang=True usage.
     # We can also check if the hash is non-zero if it was computed,
     # or if the _serializers attribute exists.
     serializer_instance = fory.type_resolver.get_serializer(DataClassObject)
diff --git a/python/pyfory/tests/test_union.py 
b/python/pyfory/tests/test_union.py
index 1bfd3745a..88607032d 100644
--- a/python/pyfory/tests/test_union.py
+++ b/python/pyfory/tests/test_union.py
@@ -87,7 +87,7 @@ def test_union_with_collections():
 
 def test_union_with_optional():
     """Test Union with Optional (Union[T, None])"""
-    fory = Fory(ref_tracking=True)
+    fory = Fory(ref=True)
 
     # Test with non-None value
     value: Union[int, None] = 42
@@ -185,7 +185,7 @@ def test_union_with_bytes():
 
 def test_union_cross_language():
     """Test Union with cross-language serialization"""
-    fory = Fory(language="xlang")
+    fory = Fory(xlang=True)
 
     # Test with int value
     value_int: Union[int, str] = 42
diff --git a/rust/fory-core/src/fory.rs b/rust/fory-core/src/fory.rs
index d4b628964..9d3f82694 100644
--- a/rust/fory-core/src/fory.rs
+++ b/rust/fory-core/src/fory.rs
@@ -24,7 +24,7 @@ use crate::resolver::type_resolver::TypeResolver;
 use crate::serializer::ForyDefault;
 use crate::serializer::{Serializer, StructSerializer};
 use crate::types::config_flags::{IS_CROSS_LANGUAGE_FLAG, IS_NULL_FLAG};
-use crate::types::{Language, RefMode, SIZE_OF_REF_AND_TYPE};
+use crate::types::{RefMode, SIZE_OF_REF_AND_TYPE};
 use std::cell::UnsafeCell;
 use std::mem;
 use std::sync::atomic::{AtomicU64, Ordering};
@@ -150,9 +150,8 @@ impl Fory {
     ///
     /// # Arguments
     ///
-    /// * `xlang` - If `true`, uses the cross-language serialization format 
that includes
-    ///   language metadata and magic numbers for compatibility with Fory 
implementations
-    ///   in other languages (Java, Python, C++, etc.). If `false`, uses a 
Rust-only
+    /// * `xlang` - If `true`, uses the cross-language serialization format 
compatible with
+    ///   other Fory implementations (Java, Python, C++, etc.). If `false`, 
uses a Rust-only
     ///   optimized format.
     ///
     /// # Returns
@@ -862,12 +861,6 @@ impl Fory {
             bitmap |= IS_NULL_FLAG;
         }
         writer.write_u8(bitmap);
-        if is_none {
-            return;
-        }
-        if self.config.xlang {
-            writer.write_u8(Language::Rust as u8);
-        }
     }
 
     /// Deserializes data from a byte slice into a value of type `T`.
@@ -1047,9 +1040,6 @@ impl Fory {
         if is_none {
             return Ok(true);
         }
-        if peer_is_xlang {
-            let _peer_lang = reader.read_u8()?;
-        }
         Ok(false)
     }
 }
diff --git a/rust/fory-core/src/meta/type_meta.rs 
b/rust/fory-core/src/meta/type_meta.rs
index 22d8f1e84..1cf9d49c4 100644
--- a/rust/fory-core/src/meta/type_meta.rs
+++ b/rust/fory-core/src/meta/type_meta.rs
@@ -99,7 +99,7 @@ pub struct FieldType {
     pub type_id: u32,
     pub user_type_id: u32,
     pub nullable: bool,
-    pub ref_tracking: bool,
+    pub track_ref: bool,
     pub generics: Vec<FieldType>,
 }
 
@@ -109,7 +109,7 @@ impl FieldType {
             type_id,
             user_type_id: NO_USER_TYPE_ID,
             nullable,
-            ref_tracking: false,
+            track_ref: false,
             generics,
         }
     }
@@ -117,14 +117,14 @@ impl FieldType {
     pub fn new_with_ref(
         type_id: u32,
         nullable: bool,
-        ref_tracking: bool,
+        track_ref: bool,
         generics: Vec<FieldType>,
     ) -> Self {
         FieldType {
             type_id,
             user_type_id: NO_USER_TYPE_ID,
             nullable,
-            ref_tracking,
+            track_ref,
             generics,
         }
     }
@@ -141,7 +141,7 @@ impl FieldType {
             if nullable {
                 header |= 2;
             }
-            if self.ref_tracking {
+            if self.track_ref {
                 header |= 1;
             }
             writer.write_var_uint32(header);
@@ -205,7 +205,7 @@ impl FieldType {
                     type_id,
                     user_type_id,
                     nullable: _nullable,
-                    ref_tracking: _ref_tracking,
+                    track_ref: _ref_tracking,
                     generics: vec![generic],
                 }
             }
@@ -216,7 +216,7 @@ impl FieldType {
                     type_id,
                     user_type_id,
                     nullable: _nullable,
-                    ref_tracking: _ref_tracking,
+                    track_ref: _ref_tracking,
                     generics: vec![key_generic, val_generic],
                 }
             }
@@ -224,7 +224,7 @@ impl FieldType {
                 type_id,
                 user_type_id,
                 nullable: _nullable,
-                ref_tracking: _ref_tracking,
+                track_ref: _ref_tracking,
                 generics: vec![],
             },
         })
@@ -269,19 +269,19 @@ impl FieldInfo {
     pub fn from_bytes(reader: &mut Reader) -> Result<FieldInfo, Error> {
         let header = reader.read_u8()?;
         let nullable = (header & 2) != 0;
-        let ref_tracking = (header & 1) != 0;
+        let track_ref = (header & 1) != 0;
         let encoding_bits = (header >> 6) & 0b11;
 
         // Check if this is field ID mode (encoding bits == 0b11)
         if encoding_bits == FIELD_ID_ENCODING_MARKER {
-            // Field ID mode: | 0b11:2bits | field_id_low:4bits | 
nullable:1bit | ref_tracking:1bit |
+            // Field ID mode: | 0b11:2bits | field_id_low:4bits | 
nullable:1bit | track_ref:1bit |
             let mut field_id = ((header >> 2) & FIELD_NAME_SIZE_THRESHOLD as 
u8) as i16;
             if field_id == SMALL_FIELD_ID_THRESHOLD {
                 field_id += reader.read_varuint32()? as i16;
             }
 
             let mut field_type = FieldType::from_bytes(reader, false, 
Option::from(nullable))?;
-            field_type.ref_tracking = ref_tracking;
+            field_type.track_ref = track_ref;
 
             Ok(FieldInfo {
                 field_id,
@@ -298,7 +298,7 @@ impl FieldInfo {
             name_size += 1;
 
             let mut field_type = FieldType::from_bytes(reader, false, 
Option::from(nullable))?;
-            field_type.ref_tracking = ref_tracking;
+            field_type.track_ref = track_ref;
 
             let field_name_bytes = reader.read_bytes(name_size)?;
 
@@ -317,17 +317,17 @@ impl FieldInfo {
         let mut buffer = vec![];
         let mut writer = Writer::from_buffer(&mut buffer);
         let nullable = self.field_type.nullable;
-        let ref_tracking = self.field_type.ref_tracking;
+        let track_ref = self.field_type.track_ref;
 
         // Use field ID encoding if:
         // 1. field_id >= 0 (user-set or matched from local type), OR
         // 2. field_name is empty (ID-encoded field that couldn't be matched - 
use ID even if -1)
         if self.field_id >= 0 || self.field_name.is_empty() {
-            // Field ID mode: | 0b11:2bits | field_id_low:4bits | 
nullable:1bit | ref_tracking:1bit |
+            // Field ID mode: | 0b11:2bits | field_id_low:4bits | 
nullable:1bit | track_ref:1bit |
             // Use max(0, field_id) to handle unmatched fields that have 
field_id = -1
             let field_id = std::cmp::max(0, self.field_id);
             let mut header: u8 = (min(SMALL_FIELD_ID_THRESHOLD, field_id) as 
u8) << 2;
-            if ref_tracking {
+            if track_ref {
                 header |= 1;
             }
             if nullable {
@@ -344,13 +344,13 @@ impl FieldInfo {
         } else {
             // Field name mode (original behavior)
             // field_bytes: | header | type_info | field_name |
-            // header: | field_name_encoding:2bits | size:4bits | 
nullability:1bit | ref_tracking:1bit |
+            // header: | field_name_encoding:2bits | size:4bits | 
nullability:1bit | track_ref:1bit |
             let meta_string =
                 FIELD_NAME_ENCODER.encode_with_encodings(&self.field_name, 
FIELD_NAME_ENCODINGS)?;
             let name_encoded = meta_string.bytes.as_slice();
             let name_size = name_encoded.len() - 1;
             let mut header: u8 = (min(FIELD_NAME_SIZE_THRESHOLD, name_size) as 
u8) << 2;
-            if ref_tracking {
+            if track_ref {
                 header |= 1;
             }
             if nullable {
diff --git a/rust/fory-core/src/serializer/skip.rs 
b/rust/fory-core/src/serializer/skip.rs
index f50b7b26e..b1b40352d 100644
--- a/rust/fory-core/src/serializer/skip.rs
+++ b/rust/fory-core/src/serializer/skip.rs
@@ -42,7 +42,7 @@ const UNKNOWN_FIELD_TYPE: FieldType = FieldType {
     type_id: types::UNKNOWN,
     user_type_id: u32::MAX,
     nullable: true,
-    ref_tracking: false,
+    track_ref: false,
     generics: vec![],
 };
 
@@ -84,7 +84,7 @@ pub fn skip_any_value(context: &mut ReadContext, 
read_ref_flag: bool) -> Result<
                 type_id,
                 user_type_id: u32::MAX,
                 nullable: true,
-                ref_tracking: false,
+                track_ref: false,
                 generics: vec![UNKNOWN_FIELD_TYPE],
             },
             None,
@@ -94,7 +94,7 @@ pub fn skip_any_value(context: &mut ReadContext, 
read_ref_flag: bool) -> Result<
                 type_id,
                 user_type_id: u32::MAX,
                 nullable: true,
-                ref_tracking: false,
+                track_ref: false,
                 generics: vec![UNKNOWN_FIELD_TYPE, UNKNOWN_FIELD_TYPE],
             },
             None,
@@ -107,7 +107,7 @@ pub fn skip_any_value(context: &mut ReadContext, 
read_ref_flag: bool) -> Result<
                     type_id,
                     user_type_id: u32::MAX,
                     nullable: true,
-                    ref_tracking: false,
+                    track_ref: false,
                     generics: vec![],
                 },
                 Some(type_info),
@@ -121,7 +121,7 @@ pub fn skip_any_value(context: &mut ReadContext, 
read_ref_flag: bool) -> Result<
                         type_id,
                         user_type_id: u32::MAX,
                         nullable: true,
-                        ref_tracking: false,
+                        track_ref: false,
                         generics: vec![],
                     },
                     Some(type_info),
@@ -140,7 +140,7 @@ pub fn skip_any_value(context: &mut ReadContext, 
read_ref_flag: bool) -> Result<
                         type_id,
                         user_type_id: u32::MAX,
                         nullable: true,
-                        ref_tracking: false,
+                        track_ref: false,
                         generics: vec![],
                     },
                     Some(type_info),
@@ -160,7 +160,7 @@ pub fn skip_any_value(context: &mut ReadContext, 
read_ref_flag: bool) -> Result<
                     type_id,
                     user_type_id: _user_type_id.unwrap_or(u32::MAX),
                     nullable: true,
-                    ref_tracking: false,
+                    track_ref: false,
                     generics: vec![],
                 },
                 type_info,
@@ -190,7 +190,7 @@ fn skip_collection(context: &mut ReadContext, field_type: 
&FieldType) -> Result<
             type_id: type_info_rc.get_type_id() as u32,
             user_type_id: type_info_rc.get_user_type_id(),
             nullable: has_null,
-            ref_tracking: false,
+            track_ref: false,
             generics: vec![],
         };
         type_info = Some(type_info_rc);
@@ -236,7 +236,7 @@ fn skip_map(context: &mut ReadContext, field_type: 
&FieldType) -> Result<(), Err
                     type_id: type_info.get_type_id() as u32,
                     user_type_id: type_info.get_user_type_id(),
                     nullable: true,
-                    ref_tracking: false,
+                    track_ref: false,
                     generics: vec![],
                 };
                 value_type_info = Some(type_info);
@@ -261,7 +261,7 @@ fn skip_map(context: &mut ReadContext, field_type: 
&FieldType) -> Result<(), Err
                     type_id: type_info.get_type_id() as u32,
                     user_type_id: type_info.get_user_type_id(),
                     nullable: true,
-                    ref_tracking: false,
+                    track_ref: false,
                     generics: vec![],
                 };
                 key_type_info = Some(type_info);
@@ -289,7 +289,7 @@ fn skip_map(context: &mut ReadContext, field_type: 
&FieldType) -> Result<(), Err
                 type_id: type_info.get_type_id() as u32,
                 user_type_id: type_info.get_user_type_id(),
                 nullable: true,
-                ref_tracking: false,
+                track_ref: false,
                 generics: vec![],
             };
             key_type_info = Some(type_info);
@@ -307,7 +307,7 @@ fn skip_map(context: &mut ReadContext, field_type: 
&FieldType) -> Result<(), Err
                 type_id: type_info.get_type_id() as u32,
                 user_type_id: type_info.get_user_type_id(),
                 nullable: true,
-                ref_tracking: false,
+                track_ref: false,
                 generics: vec![],
             };
             value_type_info = Some(type_info);
@@ -776,7 +776,7 @@ pub fn skip_enum_variant(
                 type_id: types::LIST,
                 user_type_id: u32::MAX,
                 nullable: false,
-                ref_tracking: false,
+                track_ref: false,
                 generics: vec![UNKNOWN_FIELD_TYPE],
             };
             skip_collection(context, &field_type)
diff --git a/rust/fory-core/src/types.rs b/rust/fory-core/src/types.rs
index 825fb0664..eab89a7cf 100644
--- a/rust/fory-core/src/types.rs
+++ b/rust/fory-core/src/types.rs
@@ -15,7 +15,6 @@
 // specific language governing permissions and limitations
 // under the License.
 
-use crate::error::Error;
 use num_enum::{IntoPrimitive, TryFromPrimitive};
 use std::mem;
 
@@ -497,18 +496,6 @@ pub mod config_flags {
 }
 
 #[derive(Debug, PartialEq)]
-pub enum Language {
-    Xlang = 0,
-    Java = 1,
-    Python = 2,
-    Cpp = 3,
-    Go = 4,
-    Javascript = 5,
-    Rust = 6,
-    Dart = 7,
-}
-
-#[derive(PartialEq)]
 pub enum Mode {
     // Type declaration must be consistent between serialization peer and 
deserialization peer.
     SchemaConsistent,
@@ -517,25 +504,6 @@ pub enum Mode {
     Compatible,
 }
 
-impl TryFrom<u8> for Language {
-    type Error = Error;
-
-    fn try_from(num: u8) -> Result<Self, Error> {
-        match num {
-            0 => Ok(Language::Xlang),
-            1 => Ok(Language::Java),
-            2 => Ok(Language::Python),
-            3 => Ok(Language::Cpp),
-            4 => Ok(Language::Go),
-            5 => Ok(Language::Javascript),
-            6 => Ok(Language::Rust),
-            _ => Err(Error::invalid_data(format!(
-                "Unsupported language code, value:{num}"
-            ))),
-        }
-    }
-}
-
 // every object start with i8 i16 reference flag and type flag
 pub const SIZE_OF_REF_AND_TYPE: usize = mem::size_of::<i8>() + 
mem::size_of::<i16>();
 
diff --git a/rust/fory-derive/src/object/misc.rs 
b/rust/fory-derive/src/object/misc.rs
index 0aae55a09..0e1cd8831 100644
--- a/rust/fory-derive/src/object/misc.rs
+++ b/rust/fory-derive/src/object/misc.rs
@@ -85,11 +85,11 @@ pub fn gen_field_fields_info(source_fields: 
&[SourceField<'_>]) -> TokenStream {
         let meta = parse_field_meta(field).unwrap_or_default();
         let type_class = classify_field_type(ty);
         // For nullable, check both the classified type AND whether outer type 
is Option
-        // This handles Option<Rc<T>> correctly - classify_field_type returns 
Rc for ref_tracking,
+        // This handles Option<Rc<T>> correctly - classify_field_type returns 
Rc for track_ref,
         // but we also need to detect that the outer wrapper is Option for 
nullable.
         let is_outer_option = is_option_type(ty);
         let nullable = meta.effective_nullable(type_class) || is_outer_option;
-        let ref_tracking = meta.effective_ref(type_class);
+        let track_ref = meta.effective_ref(type_class);
         // Only use explicit field ID when user sets #[fory(id = N)]
         // Otherwise use -1 to indicate field name encoding should be used
         let field_id = if meta.uses_tag_id() {
@@ -160,7 +160,7 @@ pub fn gen_field_fields_info(source_fields: 
&[SourceField<'_>]) -> TokenStream {
                                 type_id: #type_id_ts,
                                 user_type_id: u32::MAX,
                                 nullable: #nullable,
-                                ref_tracking: #ref_tracking,
+                                track_ref: #track_ref,
                                 generics: Vec::new()
                             }
                         )
@@ -183,7 +183,7 @@ pub fn gen_field_fields_info(source_fields: 
&[SourceField<'_>]) -> TokenStream {
                                 type_id: #type_id_ts,
                                 user_type_id: u32::MAX,
                                 nullable: #nullable,
-                                ref_tracking: #ref_tracking,
+                                track_ref: #track_ref,
                                 generics: Vec::new()
                             }
                         )
@@ -198,7 +198,7 @@ pub fn gen_field_fields_info(source_fields: 
&[SourceField<'_>]) -> TokenStream {
                             {
                                 let mut ft = #generic_token;
                                 ft.nullable = #nullable;
-                                ft.ref_tracking = #ref_tracking;
+                                ft.track_ref = #track_ref;
                                 ft
                             }
                         )
@@ -211,12 +211,12 @@ pub fn gen_field_fields_info(source_fields: 
&[SourceField<'_>]) -> TokenStream {
                         type_id: fory_core::types::TypeId::LIST as u32,
                         user_type_id: u32::MAX,
                         nullable: #nullable,
-                        ref_tracking: #ref_tracking,
+                        track_ref: #track_ref,
                         generics: vec![fory_core::meta::FieldType {
                             type_id: fory_core::types::TypeId::UNKNOWN as u32,
                             user_type_id: u32::MAX,
                             nullable: false,
-                            ref_tracking: false,
+                            track_ref: false,
                             generics: Vec::new()
                         }]
                     })
@@ -232,14 +232,14 @@ pub fn gen_field_fields_info(source_fields: 
&[SourceField<'_>]) -> TokenStream {
                         type_id: fory_core::types::TypeId::MAP as u32,
                         user_type_id: u32::MAX,
                         nullable: #nullable,
-                        ref_tracking: #ref_tracking,
+                        track_ref: #track_ref,
                         generics: vec![
                             #key_generic_token,
                             fory_core::meta::FieldType {
                                 type_id: fory_core::types::TypeId::UNKNOWN as 
u32,
                                 user_type_id: u32::MAX,
                                 nullable: false,
-                                ref_tracking: false,
+                                track_ref: false,
                                 generics: Vec::new()
                             }
                         ]
@@ -252,7 +252,7 @@ pub fn gen_field_fields_info(source_fields: 
&[SourceField<'_>]) -> TokenStream {
                         type_id: fory_core::types::TypeId::UNKNOWN as u32,
                         user_type_id: u32::MAX,
                         nullable: #nullable,
-                        ref_tracking: #ref_tracking,
+                        track_ref: #track_ref,
                         generics: Vec::new()
                     })
                 }
diff --git a/rust/fory-derive/src/object/read.rs 
b/rust/fory-derive/src/object/read.rs
index 2635f3b71..ba1e7aa44 100644
--- a/rust/fory-derive/src/object/read.rs
+++ b/rust/fory-derive/src/object/read.rs
@@ -591,20 +591,20 @@ pub(crate) fn gen_read_compatible_match_arm_body(
             }
             StructField::VecBox(_) => {
                 // Vec<Box<dyn Any>> uses standard Vec deserialization with 
polymorphic elements
-                // Check nullable and ref_tracking flags from remote field info
+                // Check nullable and track_ref flags from remote field info
                 quote! {
                     let read_ref_flag = 
fory_core::serializer::util::field_need_write_ref_into(
                         _field.field_type.type_id,
                         _field.field_type.nullable,
                     );
-                    let ref_mode = if _field.field_type.ref_tracking {
+                    let ref_mode = if _field.field_type.track_ref {
                         fory_core::RefMode::Tracking
                     } else if read_ref_flag {
                         fory_core::RefMode::NullOnly
                     } else {
                         fory_core::RefMode::None
                     };
-                    if read_ref_flag || _field.field_type.ref_tracking {
+                    if read_ref_flag || _field.field_type.track_ref {
                         #var_name = Some(<#ty as 
fory_core::Serializer>::fory_read(context, ref_mode, false)?);
                     } else {
                         #var_name = Some(<#ty as 
fory_core::Serializer>::fory_read_data(context)?);
@@ -613,20 +613,20 @@ pub(crate) fn gen_read_compatible_match_arm_body(
             }
             StructField::HashMapBox(_, _) => {
                 // HashMap<K, Box<dyn Any>> uses standard HashMap 
deserialization with polymorphic values
-                // Check nullable and ref_tracking flags from remote field info
+                // Check nullable and track_ref flags from remote field info
                 quote! {
                     let read_ref_flag = 
fory_core::serializer::util::field_need_write_ref_into(
                         _field.field_type.type_id,
                         _field.field_type.nullable,
                     );
-                    let ref_mode = if _field.field_type.ref_tracking {
+                    let ref_mode = if _field.field_type.track_ref {
                         fory_core::RefMode::Tracking
                     } else if read_ref_flag {
                         fory_core::RefMode::NullOnly
                     } else {
                         fory_core::RefMode::None
                     };
-                    if read_ref_flag || _field.field_type.ref_tracking {
+                    if read_ref_flag || _field.field_type.track_ref {
                         #var_name = Some(<#ty as 
fory_core::Serializer>::fory_read(context, ref_mode, false)?);
                     } else {
                         #var_name = Some(<#ty as 
fory_core::Serializer>::fory_read_data(context)?);
@@ -665,14 +665,14 @@ pub(crate) fn gen_read_compatible_match_arm_body(
             }
             StructField::Forward => {
                 // Forward types (trait objects, forward references) - 
polymorphic, always need type info
-                // Use remote field's ref_tracking flag for ref_mode
+                // Use remote field's track_ref flag for ref_mode
                 quote! {
                     let read_ref_flag = 
fory_core::serializer::util::field_need_write_ref_into(
                         _field.field_type.type_id,
                         _field.field_type.nullable,
                     );
-                    // Use RefMode::Tracking if remote field has ref_tracking 
enabled
-                    let ref_mode = if _field.field_type.ref_tracking {
+                    // Use RefMode::Tracking if remote field has track_ref 
enabled
+                    let ref_mode = if _field.field_type.track_ref {
                         fory_core::RefMode::Tracking
                     } else if read_ref_flag {
                         fory_core::RefMode::NullOnly
@@ -711,15 +711,15 @@ pub(crate) fn gen_read_compatible_match_arm_body(
                                 _field.field_type.type_id,
                                 _field.field_type.nullable,
                             );
-                            // Use RefMode::Tracking if remote field has 
ref_tracking enabled
-                            let ref_mode = if _field.field_type.ref_tracking {
+                            // Use RefMode::Tracking if remote field has 
track_ref enabled
+                            let ref_mode = if _field.field_type.track_ref {
                                 fory_core::RefMode::Tracking
                             } else if read_ref_flag {
                                 fory_core::RefMode::NullOnly
                             } else {
                                 fory_core::RefMode::None
                             };
-                            if read_ref_flag || _field.field_type.ref_tracking 
{
+                            if read_ref_flag || _field.field_type.track_ref {
                                 #var_name = Some(<#ty as 
fory_core::Serializer>::fory_read(context, ref_mode, false)?);
                             } else {
                                 #var_name = Some(<#ty as 
fory_core::Serializer>::fory_read_data(context)?);
@@ -732,8 +732,8 @@ pub(crate) fn gen_read_compatible_match_arm_body(
                                 _field.field_type.type_id,
                                 _field.field_type.nullable,
                             );
-                            // Use RefMode::Tracking if remote field has 
ref_tracking enabled
-                            let ref_mode = if _field.field_type.ref_tracking {
+                            // Use RefMode::Tracking if remote field has 
track_ref enabled
+                            let ref_mode = if _field.field_type.track_ref {
                                 fory_core::RefMode::Tracking
                             } else if read_ref_flag {
                                 fory_core::RefMode::NullOnly
@@ -754,15 +754,15 @@ pub(crate) fn gen_read_compatible_match_arm_body(
                                 _field.field_type.type_id,
                                 _field.field_type.nullable,
                             );
-                            // Use RefMode::Tracking if remote field has 
ref_tracking enabled
-                            let ref_mode = if _field.field_type.ref_tracking {
+                            // Use RefMode::Tracking if remote field has 
track_ref enabled
+                            let ref_mode = if _field.field_type.track_ref {
                                 fory_core::RefMode::Tracking
                             } else if read_ref_flag {
                                 fory_core::RefMode::NullOnly
                             } else {
                                 fory_core::RefMode::None
                             };
-                            if read_ref_flag || _field.field_type.ref_tracking 
{
+                            if read_ref_flag || _field.field_type.track_ref {
                                 #var_name = Some(<#ty as 
fory_core::Serializer>::fory_read(context, ref_mode, false)?);
                             } else {
                                 #var_name = Some(<#ty as 
fory_core::Serializer>::fory_read_data(context)?);
@@ -774,15 +774,15 @@ pub(crate) fn gen_read_compatible_match_arm_body(
                                 _field.field_type.type_id,
                                 _field.field_type.nullable,
                             );
-                            // Use RefMode::Tracking if remote field has 
ref_tracking enabled
-                            let ref_mode = if _field.field_type.ref_tracking {
+                            // Use RefMode::Tracking if remote field has 
track_ref enabled
+                            let ref_mode = if _field.field_type.track_ref {
                                 fory_core::RefMode::Tracking
                             } else if read_ref_flag {
                                 fory_core::RefMode::NullOnly
                             } else {
                                 fory_core::RefMode::None
                             };
-                            if read_ref_flag || _field.field_type.ref_tracking 
{
+                            if read_ref_flag || _field.field_type.track_ref {
                                 #var_name = <#ty as 
fory_core::Serializer>::fory_read(context, ref_mode, false)?;
                             } else {
                                 #var_name = <#ty as 
fory_core::Serializer>::fory_read_data(context)?;
@@ -795,8 +795,8 @@ pub(crate) fn gen_read_compatible_match_arm_body(
                             _field.field_type.type_id,
                             _field.field_type.nullable,
                         );
-                        // Use RefMode::Tracking if remote field has 
ref_tracking enabled
-                        let ref_mode = if _field.field_type.ref_tracking {
+                        // Use RefMode::Tracking if remote field has track_ref 
enabled
+                        let ref_mode = if _field.field_type.track_ref {
                             fory_core::RefMode::Tracking
                         } else if read_ref_flag {
                             fory_core::RefMode::NullOnly
@@ -815,8 +815,8 @@ pub(crate) fn gen_read_compatible_match_arm_body(
                             _field.field_type.type_id,
                             _field.field_type.nullable,
                         );
-                        // Use RefMode::Tracking if remote field has 
ref_tracking enabled
-                        let ref_mode = if _field.field_type.ref_tracking {
+                        // Use RefMode::Tracking if remote field has track_ref 
enabled
+                        let ref_mode = if _field.field_type.track_ref {
                             fory_core::RefMode::Tracking
                         } else if read_ref_flag {
                             fory_core::RefMode::NullOnly
diff --git a/rust/fory-derive/src/object/util.rs 
b/rust/fory-derive/src/object/util.rs
index 5080a4bc9..84c8f9fb0 100644
--- a/rust/fory-derive/src/object/util.rs
+++ b/rust/fory-derive/src/object/util.rs
@@ -593,7 +593,7 @@ pub(super) fn generic_tree_to_tokens(node: &TypeNode) -> 
TokenStream {
     };
 
     // If Rc or Arc, unwrap to inner type - these are reference wrappers
-    // that don't add type info to the field type (handled by ref_tracking 
flag)
+    // that don't add type info to the field type (handled by track_ref flag)
     let base_node = if base_node.name == "Rc" || base_node.name == "Arc" {
         if let Some(inner) = base_node.generics.first() {
             inner
@@ -674,7 +674,7 @@ pub(super) fn generic_tree_to_tokens(node: &TypeNode) -> 
TokenStream {
                 type_id,
                 user_type_id,
                 nullable: #nullable,
-                ref_tracking: false,
+                track_ref: false,
                 generics,
             }
         }
@@ -1321,7 +1321,7 @@ struct FieldFingerprintInfo {
     /// Whether the field has explicit nullable=true/false set via 
#[fory(nullable)]
     explicit_nullable: Option<bool>,
     /// Whether reference tracking is enabled
-    ref_tracking: bool,
+    track_ref: bool,
     /// The type ID (UNKNOWN for user-defined types including enums/unions)
     type_id: u32,
     /// Whether the field type is `Option<T>`
@@ -1409,7 +1409,7 @@ fn compute_struct_fingerprint(fields: &[&Field]) -> 
String {
         };
 
         let type_class = classify_field_type(&field.ty);
-        let ref_tracking = meta.effective_ref(type_class);
+        let track_ref = meta.effective_ref(type_class);
         let explicit_nullable = meta.nullable;
 
         // Get compile-time TypeId, considering encoding attributes for 
u32/u64 fields
@@ -1429,7 +1429,7 @@ fn compute_struct_fingerprint(fields: &[&Field]) -> 
String {
         field_infos.push(FieldFingerprintInfo {
             name_or_id,
             explicit_nullable,
-            ref_tracking,
+            track_ref,
             type_id,
             is_option_type,
         });
@@ -1441,7 +1441,7 @@ fn compute_struct_fingerprint(fields: &[&Field]) -> 
String {
     // Build fingerprint string
     let mut fingerprint = String::new();
     for info in &field_infos {
-        let ref_flag = if info.ref_tracking { "1" } else { "0" };
+        let ref_flag = if info.track_ref { "1" } else { "0" };
         let nullable = match info.explicit_nullable {
             Some(true) => true,
             Some(false) => false,
@@ -1522,9 +1522,9 @@ pub(crate) fn determine_field_ref_mode(field: 
&syn::Field) -> FieldRefMode {
     let meta = parse_field_meta(field).unwrap_or_default();
     let type_class = classify_field_type(&field.ty);
     let nullable = meta.effective_nullable(type_class);
-    let ref_tracking = meta.effective_ref(type_class);
+    let track_ref = meta.effective_ref(type_class);
 
-    if ref_tracking {
+    if track_ref {
         FieldRefMode::Tracking
     } else if nullable {
         FieldRefMode::NullOnly
diff --git a/rust/tests/tests/test_meta.rs b/rust/tests/tests/test_meta.rs
index 4d32296b8..deae54dd7 100644
--- a/rust/tests/tests/test_meta.rs
+++ b/rust/tests/tests/test_meta.rs
@@ -33,7 +33,7 @@ fn test_meta_hash() {
                 type_id: TypeId::BOOL as u32,
                 user_type_id: u32::MAX,
                 nullable: true,
-                ref_tracking: false,
+                track_ref: false,
                 generics: vec![],
             },
         }],


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to