Skip to content

Add support for GlobalTranslator#40

Merged
Tofaa2 merged 2 commits intoTofaa2:masterfrom
huanmeng-qwq:feat/translation-render
Jul 21, 2025
Merged

Add support for GlobalTranslator#40
Tofaa2 merged 2 commits intoTofaa2:masterfrom
huanmeng-qwq:feat/translation-render

Conversation

@huanmeng-qwq
Copy link
Contributor

@huanmeng-qwq huanmeng-qwq commented Jul 21, 2025

Summary by CodeRabbit

  • New Features

    • Introduced a user locale provider system, enabling detection and use of individual user locales across all supported platforms.
    • Added platform-specific locale provider implementations for Spigot and Velocity environments.
    • Enhanced packet handling to support locale-aware rendering of entity metadata.
  • Improvements

    • Platforms and API interfaces now allow getting and setting a user locale provider for greater flexibility in locale management.

@coderabbitai
Copy link

coderabbitai bot commented Jul 21, 2025

Walkthrough

This update introduces a user locale provider abstraction across the codebase. It adds the UserLocaleProvider interface and integrates it into the core API, platform implementations (Spigot, Velocity, Standalone), and entity packet handling utilities. New classes and methods enable locale-aware component rendering for entity metadata packets, with platform-specific locale resolution logic.

Changes

File(s) / Group Change Summary
api/src/main/java/me/tofaa/entitylib/EntityLibAPI.java
common/.../AbstractEntityLibAPI.java
Added getUserLocaleProvider() method to API and abstract implementation.
api/src/main/java/me/tofaa/entitylib/Platform.java Added getUserLocaleProvider() and setUserLocaleProvider() methods to the platform interface.
api/src/main/java/me/tofaa/entitylib/UserLocaleProvider.java Introduced UserLocaleProvider interface for user-locale resolution.
api/src/main/java/me/tofaa/entitylib/utils/PacketUtil.java Added PacketUtil utility class with renderPacket() for locale-aware component rendering in entity metadata.
api/src/main/java/me/tofaa/entitylib/wrapper/WrapperEntity.java Updated packet sending logic to use PacketUtil.renderPacket() for entity metadata packets.
platforms/spigot/src/main/java/me/tofaa/entitylib/spigot/SpigotEntityLibPlatform.java Added user locale provider field, getter, setter; initialized with SpigotPlayerLocaleProvider.
platforms/spigot/src/main/java/me/tofaa/entitylib/spigot/SpigotPlayerLocaleProvider.java Introduced locale provider for Spigot, with dynamic method resolution for player locale retrieval.
platforms/standalone/src/main/java/me/tofaa/entitylib/standalone/StandaloneEntityLibPlatform.java Added user locale provider field, getter, setter; default provider returns Locale.US.
platforms/velocity/src/main/java/me/tofaa/entitylib/velocity/VelocityEntityLibPlatform.java Added user locale provider field, getter, setter for Velocity platform.
platforms/velocity/src/main/java/me/tofaa/entitylib/velocity/VelocityPlayerLocaleProvider.java Introduced locale provider for Velocity, resolving locale from ProxyServer or defaulting to Locale.US.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant WrapperEntity
    participant PacketUtil
    participant EntityLibAPI
    participant UserLocaleProvider

    Client->>WrapperEntity: sendPacket(user, packet)
    alt packet is EntityMetadata
        WrapperEntity->>PacketUtil: renderPacket(user, metadata)
        PacketUtil->>EntityLibAPI: getUserLocaleProvider()
        EntityLibAPI->>UserLocaleProvider: locale(user)
        UserLocaleProvider-->>PacketUtil: Locale
        PacketUtil-->>WrapperEntity: Rendered metadata
    end
    WrapperEntity->>ProtocolManager: sendPacket(user, packet)
Loading

Estimated code review effort

4 (~90 minutes)

Poem

🐇
Hopping through code, I sniff the new scent—
Locale providers, on every event!
Now packets can greet in the tongue you know,
From Spigot to Velocity, let translations flow.
With every UUID, a language anew—
This rabbit says: "Great job, team—merci, 谢谢, and thank you!"
🌍✨

✨ Finishing Touches
  • 📝 Generate Docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@huanmeng-qwq huanmeng-qwq changed the title Feat/translation render Add support for GlobalTranslator Jul 21, 2025
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 11

🧹 Nitpick comments (2)
api/src/main/java/me/tofaa/entitylib/EntityLibAPI.java (1)

56-57: Add JavaDoc documentation for the new API method.

The new method lacks documentation explaining its purpose and usage within the EntityLib ecosystem.

+    /**
+     * Gets the user locale provider for this API instance.
+     * The provider is used to determine user locales for locale-aware packet rendering.
+     *
+     * @return the user locale provider, never null
+     */
     @NotNull
     UserLocaleProvider getUserLocaleProvider();
platforms/spigot/src/main/java/me/tofaa/entitylib/spigot/SpigotPlayerLocaleProvider.java (1)

31-72: Consider adding debug logging for API detection

The static initialization tries multiple APIs silently. Consider adding debug logging to help diagnose which API is being used in production environments.

You could add a logger to track which locale retrieval method is being used:

private static final Logger LOGGER = Logger.getLogger(SpigotPlayerLocaleProvider.class.getName());

// In each successful branch:
LOGGER.fine("Using Adventure API for locale retrieval");
// or
LOGGER.fine("Using legacy Spigot API for locale retrieval");
// or  
LOGGER.fine("Using legacy Player API for locale retrieval");

This would help with debugging locale-related issues in different server environments.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d6a3cb7 and acbb438.

📒 Files selected for processing (11)
  • api/src/main/java/me/tofaa/entitylib/EntityLibAPI.java (1 hunks)
  • api/src/main/java/me/tofaa/entitylib/Platform.java (2 hunks)
  • api/src/main/java/me/tofaa/entitylib/UserLocaleProvider.java (1 hunks)
  • api/src/main/java/me/tofaa/entitylib/utils/PacketUtil.java (1 hunks)
  • api/src/main/java/me/tofaa/entitylib/wrapper/WrapperEntity.java (2 hunks)
  • common/src/main/java/me/tofaa/entitylib/common/AbstractEntityLibAPI.java (2 hunks)
  • platforms/spigot/src/main/java/me/tofaa/entitylib/spigot/SpigotEntityLibPlatform.java (3 hunks)
  • platforms/spigot/src/main/java/me/tofaa/entitylib/spigot/SpigotPlayerLocaleProvider.java (1 hunks)
  • platforms/standalone/src/main/java/me/tofaa/entitylib/standalone/StandaloneEntityLibPlatform.java (2 hunks)
  • platforms/velocity/src/main/java/me/tofaa/entitylib/velocity/VelocityEntityLibPlatform.java (2 hunks)
  • platforms/velocity/src/main/java/me/tofaa/entitylib/velocity/VelocityPlayerLocaleProvider.java (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (4)
api/src/main/java/me/tofaa/entitylib/wrapper/WrapperEntity.java (2)
api/src/main/java/me/tofaa/entitylib/EntityLib.java (1)
  • EntityLib (9-39)
api/src/main/java/me/tofaa/entitylib/utils/PacketUtil.java (1)
  • PacketUtil (13-34)
api/src/main/java/me/tofaa/entitylib/utils/PacketUtil.java (1)
api/src/main/java/me/tofaa/entitylib/EntityLib.java (1)
  • EntityLib (9-39)
platforms/standalone/src/main/java/me/tofaa/entitylib/standalone/StandaloneEntityLibPlatform.java (1)
common/src/main/java/me/tofaa/entitylib/common/AbstractPlatform.java (1)
  • AbstractPlatform (11-73)
platforms/spigot/src/main/java/me/tofaa/entitylib/spigot/SpigotEntityLibPlatform.java (1)
common/src/main/java/me/tofaa/entitylib/common/AbstractPlatform.java (1)
  • AbstractPlatform (11-73)
🔇 Additional comments (14)
common/src/main/java/me/tofaa/entitylib/common/AbstractEntityLibAPI.java (2)

7-7: Proper import addition for the new interface.

The import is correctly added to support the new functionality.


68-71: Clean implementation following established patterns.

The implementation correctly delegates to the platform instance, maintaining consistency with other methods in this abstract class.

api/src/main/java/me/tofaa/entitylib/Platform.java (2)

29-34: Excellent documentation and interface design.

The getter method is well-documented with clear JavaDoc, proper null annotations, and follows established naming conventions.


48-53: Well-structured setter with comprehensive documentation.

The setter method includes proper parameter documentation, null safety requirements, and maintains consistency with other setter methods in the interface.

api/src/main/java/me/tofaa/entitylib/wrapper/WrapperEntity.java (1)

8-17: LGTM! Import organization improved.

The change from wildcard imports to explicit imports improves code clarity and follows Java best practices. All new imports are properly utilized in the implementation.

Also applies to: 23-23, 26-34

platforms/standalone/src/main/java/me/tofaa/entitylib/standalone/StandaloneEntityLibPlatform.java (3)

5-5: LGTM! Necessary imports added.

The imports are properly used in the implementation below.

Also applies to: 7-7


14-14: Good default locale choice for standalone platform.

Using Locale.US as the default for standalone environments is a sensible choice when no specific user locale context is available.


41-49: Interface implementation complete and correct.

The getter and setter methods properly implement the Platform interface contract with appropriate annotations and null safety.

platforms/spigot/src/main/java/me/tofaa/entitylib/spigot/SpigotEntityLibPlatform.java (3)

8-8: Import organization improved.

The new UserLocaleProvider import is necessary, and the import reorganization improves code structure.

Also applies to: 10-10


18-18: Appropriate platform-specific locale provider.

Using SpigotPlayerLocaleProvider is the correct choice for the Spigot platform, providing access to Bukkit player locale information.


50-58: Interface methods properly implemented.

The getter and setter methods correctly implement the platform interface with proper annotations and type safety.

api/src/main/java/me/tofaa/entitylib/utils/PacketUtil.java (1)

1-16: Well-structured utility class.

The class follows proper utility class patterns with a private constructor and comprehensive imports. The package placement in utils is appropriate.

platforms/velocity/src/main/java/me/tofaa/entitylib/velocity/VelocityEntityLibPlatform.java (1)

12-12: Necessary import added.

The UserLocaleProvider import is required for the new locale management functionality.

platforms/spigot/src/main/java/me/tofaa/entitylib/spigot/SpigotPlayerLocaleProvider.java (1)

16-23: Good attribution and class structure!

The attribution comment properly credits the original source, and the class structure with static initialization is appropriate for this use case.

Comment on lines +6 to +8
public interface UserLocaleProvider {
Locale locale(UUID user);
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add null annotations and documentation for better API clarity.

The interface lacks proper documentation and null safety annotations. Consider the following improvements:

+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * Provides user locale information based on user UUID.
+ * Implementations should handle cases where users are not found gracefully.
+ */
 public interface UserLocaleProvider {
-    Locale locale(UUID user);
+    /**
+     * Retrieves the locale for the specified user.
+     *
+     * @param user the UUID of the user, must not be null
+     * @return the user's locale, or a default locale if the user is not found
+     */
+    @NotNull Locale getUserLocale(@NotNull UUID user);
 }

The method name locale should also be more descriptive - getUserLocale clearly indicates what the method does.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
public interface UserLocaleProvider {
Locale locale(UUID user);
}
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* Provides user locale information based on user UUID.
* Implementations should handle cases where users are not found gracefully.
*/
public interface UserLocaleProvider {
/**
* Retrieves the locale for the specified user.
*
* @param user the UUID of the user, must not be null
* @return the user's locale, or a default locale if the user is not found
*/
@NotNull
Locale getUserLocale(@NotNull UUID user);
}
🤖 Prompt for AI Agents
In api/src/main/java/me/tofaa/entitylib/UserLocaleProvider.java around lines 6
to 8, add JavaDoc comments to the interface and its method to clarify their
purpose. Rename the method from locale to getUserLocale for better
descriptiveness. Add appropriate nullability annotations such as @Nullable or
@NonNull to the method parameter and return type to improve null safety and API
clarity.

Comment on lines +17 to +33
public static void renderPacket(UUID user, WrapperPlayServerEntityMetadata metadata) {
Locale locale = EntityLib.getApi().getUserLocaleProvider().locale(user);
for (final EntityData<?> entityData : metadata.getEntityMetadata()) {
if (entityData.getType() == EntityDataTypes.ADV_COMPONENT) {
Component component = (Component) entityData.getValue();
final Component rendered = GlobalTranslator.render(component, locale);
((EntityData<Component>) entityData).setValue(rendered);
} else if (entityData.getType() == EntityDataTypes.OPTIONAL_ADV_COMPONENT) {
final Optional<Component> optional = (Optional<Component>) entityData.getValue();
if (optional.isPresent()) {
final Component component = optional.get();
final Component rendered = GlobalTranslator.render(component, locale);
((EntityData<Optional<Component>>) entityData).setValue(Optional.of(rendered));
}
}
}
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Core logic is sound but needs safety improvements.

The method correctly handles both ADV_COMPONENT and OPTIONAL_ADV_COMPONENT types for locale-aware rendering. However, there are safety concerns:

  1. Unsafe casting: The casts on lines 21, 23, 25, and 29 could throw ClassCastException if the entity data types don't match expectations.
  2. Missing null checks: No validation that locale, component, or optional are non-null.
  3. Error handling: No handling if getUserLocaleProvider().locale(user) fails.

Consider adding safety checks:

 public static void renderPacket(UUID user, WrapperPlayServerEntityMetadata metadata) {
+    UserLocaleProvider provider = EntityLib.getApi().getUserLocaleProvider();
+    if (provider == null) return;
+    
-    Locale locale = EntityLib.getApi().getUserLocaleProvider().locale(user);
+    Locale locale = provider.locale(user);
+    if (locale == null) return;
+    
     for (final EntityData<?> entityData : metadata.getEntityMetadata()) {
         if (entityData.getType() == EntityDataTypes.ADV_COMPONENT) {
-            Component component = (Component) entityData.getValue();
+            Object value = entityData.getValue();
+            if (!(value instanceof Component)) continue;
+            Component component = (Component) value;
+            if (component == null) continue;
             final Component rendered = GlobalTranslator.render(component, locale);
             ((EntityData<Component>) entityData).setValue(rendered);
         } else if (entityData.getType() == EntityDataTypes.OPTIONAL_ADV_COMPONENT) {
-            final Optional<Component> optional = (Optional<Component>) entityData.getValue();
+            Object value = entityData.getValue();
+            if (!(value instanceof Optional)) continue;
+            final Optional<Component> optional = (Optional<Component>) value;
             if (optional.isPresent()) {
                 final Component component = optional.get();
+                if (component == null) continue;
                 final Component rendered = GlobalTranslator.render(component, locale);
                 ((EntityData<Optional<Component>>) entityData).setValue(Optional.of(rendered));
             }
         }
     }
 }
🤖 Prompt for AI Agents
In api/src/main/java/me/tofaa/entitylib/utils/PacketUtil.java between lines 17
and 33, the method renderPacket performs unsafe casts on entityData values and
lacks null checks and error handling. To fix this, add checks to ensure locale
is not null before proceeding, verify that the values retrieved from entityData
are non-null before casting and rendering, and use instanceof checks or
try-catch blocks to safely cast entityData values to avoid ClassCastException.
Also, handle potential exceptions or null returns from
getUserLocaleProvider().locale(user) gracefully to prevent runtime errors.

Comment on lines +527 to +530
// Special handling for entity metadata packets to support `GlobalTranslator` functionality and component rendering
if (wrapper instanceof WrapperPlayServerEntityMetadata) {
PacketUtil.renderPacket(user, (WrapperPlayServerEntityMetadata) wrapper);
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Good integration of locale-aware component rendering.

The special handling for entity metadata packets is well-implemented and properly placed before packet transmission. The instanceof check is efficient and the cast is safe.

Consider adding error handling around PacketUtil.renderPacket() to prevent packet sending failures if locale processing encounters issues.


🏁 Script executed:

#!/bin/bash
# Verify PacketUtil.renderPacket error handling
rg -A 10 -B 5 "renderPacket.*throws|catch.*renderPacket" --type java

Length of output: 70


🏁 Script executed:

#!/bin/bash
# Locate PacketUtil class and inspect renderPacket method declaration for exception behavior
rg -n "class PacketUtil" --type java
rg -A5 -B2 "renderPacket(" --type java

Length of output: 244


🏁 Script executed:

#!/bin/bash
# Find all occurrences of `renderPacket` to locate its definition
rg -n "renderPacket" --type java

# Once the file is identified, show the method declaration with surrounding context
rg -C5 "renderPacket" api/src/main/java/me/tofaa/entitylib/utils/PacketUtil.java

Length of output: 964


Add runtime error handling around PacketUtil.renderPacket

The renderPacket method doesn’t declare checked exceptions, so any failures (for example, NPEs during locale rendering) would be unchecked and could propagate, potentially interrupting packet transmission. Wrap the call in a try/catch for RuntimeException and log the error to ensure the packet still sends.

• File: api/src/main/java/me/tofaa/entitylib/wrapper/WrapperEntity.java
Around lines 527–530

Suggested diff:

-        if (wrapper instanceof WrapperPlayServerEntityMetadata) {
-            PacketUtil.renderPacket(user, (WrapperPlayServerEntityMetadata) wrapper);
-        }
+        if (wrapper instanceof WrapperPlayServerEntityMetadata) {
+            try {
+                PacketUtil.renderPacket(user, (WrapperPlayServerEntityMetadata) wrapper);
+            } catch (RuntimeException e) {
+                EntityLib.getLogger()
+                         .error("Failed to render entity metadata packet for user {}", user, e);
+            }
+        }
🤖 Prompt for AI Agents
In api/src/main/java/me/tofaa/entitylib/wrapper/WrapperEntity.java around lines
527 to 530, the call to PacketUtil.renderPacket can throw unchecked runtime
exceptions that may disrupt packet transmission. Wrap this call in a try/catch
block catching RuntimeException, and log the exception to prevent interruption
while still sending the packet.

Comment on lines +26 to +29
public Locale locale(final UUID user) {
final Player player = Bukkit.getPlayer(user);
return player == null ? DEFAULT_LOCALE : provider.apply(player);
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Consider handling potential race conditions

There's a potential race condition where a player could disconnect between the null check and provider.apply(player). Consider wrapping the entire operation in a try-catch block to handle any exceptions gracefully.

 @Override
 public Locale locale(final UUID user) {
     final Player player = Bukkit.getPlayer(user);
-    return player == null ? DEFAULT_LOCALE : provider.apply(player);
+    if (player == null) {
+        return DEFAULT_LOCALE;
+    }
+    try {
+        return provider.apply(player);
+    } catch (RuntimeException e) {
+        // Player might have disconnected or other issues
+        return DEFAULT_LOCALE;
+    }
 }

🏁 Script executed:

#!/bin/bash
# Locate and display the SpigotPlayerLocaleProvider implementation for review
fd SpigotPlayerLocaleProvider.java -type f -x sed -n '1,200p' {}

Length of output: 237


🏁 Script executed:

#!/bin/bash
# Corrected script to locate and display the SpigotPlayerLocaleProvider implementation
file=$(find . -type f -name SpigotPlayerLocaleProvider.java)
if [ -z "$file" ]; then
  echo "SpigotPlayerLocaleProvider.java not found"
  exit 1
fi
echo "Found file at: $file"
sed -n '1,200p' "$file"

Length of output: 3649


Handle reflection exceptions in locale to prevent runtime errors

Wrap the call to provider.apply(player) in a try/catch so that any RuntimeException thrown by the reflection-based lookup falls back to DEFAULT_LOCALE rather than bubbling up.

Locations to update:

  • platforms/spigot/src/main/java/me/tofaa/entitylib/spigot/SpigotPlayerLocaleProvider.java – the locale(UUID) method

Suggested diff:

 @Override
 public Locale locale(final UUID user) {
     final Player player = Bukkit.getPlayer(user);
-    return player == null ? DEFAULT_LOCALE : provider.apply(player);
+    if (player == null) {
+        return DEFAULT_LOCALE;
+    }
+    try {
+        return provider.apply(player);
+    } catch (RuntimeException e) {
+        // Fallback to default locale if reflective lookup fails
+        return DEFAULT_LOCALE;
+    }
 }
🤖 Prompt for AI Agents
In
platforms/spigot/src/main/java/me/tofaa/entitylib/spigot/SpigotPlayerLocaleProvider.java
around lines 26 to 29, the locale(UUID) method calls provider.apply(player)
which may throw a RuntimeException due to reflection issues. Wrap the call to
provider.apply(player) in a try/catch block catching RuntimeException, and
return DEFAULT_LOCALE in the catch block to prevent runtime errors from
propagating.

Comment on lines +35 to +41
return player -> {
try {
return (Locale) adventureMethod.invokeExact(player);
} catch (Throwable e) {
throw new RuntimeException(e);
}
};
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Preserve stack traces when rethrowing exceptions

When catching and rethrowing exceptions, preserve the original stack trace for better debugging.

 return player -> {
     try {
         return (Locale) adventureMethod.invokeExact(player);
     } catch (Throwable e) {
-        throw new RuntimeException(e);
+        throw new RuntimeException("Failed to get locale via Adventure API", e);
     }
 };
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
return player -> {
try {
return (Locale) adventureMethod.invokeExact(player);
} catch (Throwable e) {
throw new RuntimeException(e);
}
};
return player -> {
try {
return (Locale) adventureMethod.invokeExact(player);
} catch (Throwable e) {
throw new RuntimeException("Failed to get locale via Adventure API", e);
}
};
🤖 Prompt for AI Agents
In
platforms/spigot/src/main/java/me/tofaa/entitylib/spigot/SpigotPlayerLocaleProvider.java
around lines 35 to 41, the caught Throwable is rethrown by wrapping it in a new
RuntimeException without preserving the original stack trace. To fix this,
ensure the original exception is passed as the cause to the RuntimeException
constructor so the stack trace is preserved for better debugging.

Comment on lines +61 to +68
return player -> {
try {
Locale locale = Translator.parseLocale((String) legacyMethod.invokeExact(player));
return locale == null ? DEFAULT_LOCALE : locale;
} catch (Throwable e) {
throw new RuntimeException(e);
}
};
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Apply consistent exception handling improvements

Apply the same exception handling improvement here.

 return player -> {
     try {
         Locale locale = Translator.parseLocale((String) legacyMethod.invokeExact(player));
         return locale == null ? DEFAULT_LOCALE : locale;
     } catch (Throwable e) {
-        throw new RuntimeException(e);
+        throw new RuntimeException("Failed to get locale via legacy API", e);
     }
 };
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
return player -> {
try {
Locale locale = Translator.parseLocale((String) legacyMethod.invokeExact(player));
return locale == null ? DEFAULT_LOCALE : locale;
} catch (Throwable e) {
throw new RuntimeException(e);
}
};
return player -> {
try {
Locale locale = Translator.parseLocale((String) legacyMethod.invokeExact(player));
return locale == null ? DEFAULT_LOCALE : locale;
} catch (Throwable e) {
throw new RuntimeException("Failed to get locale via legacy API", e);
}
};
🤖 Prompt for AI Agents
In
platforms/spigot/src/main/java/me/tofaa/entitylib/spigot/SpigotPlayerLocaleProvider.java
around lines 61 to 68, the exception handling wraps all exceptions in a
RuntimeException without preserving the original exception type or message
clearly. Refactor the catch block to handle exceptions more consistently by
logging the error or rethrowing a more specific exception with the original
exception as the cause, ensuring better clarity and maintainability in error
handling.


public class VelocityEntityLibPlatform extends AbstractPlatform<ProxyServer> {
private VelocityEntityLibAPI api;
private UserLocaleProvider userLocaleProvider;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Missing field initialization could cause NPE.

The userLocaleProvider field is not initialized, which could lead to NullPointerException if getUserLocaleProvider() is called before setUserLocaleProvider(). Consider providing a default implementation like other platforms.

-private UserLocaleProvider userLocaleProvider;
+private UserLocaleProvider userLocaleProvider = new VelocityPlayerLocaleProvider(handle);

Or provide a safe fallback:

-private UserLocaleProvider userLocaleProvider;
+private UserLocaleProvider userLocaleProvider = (user) -> Locale.US;

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In
platforms/velocity/src/main/java/me/tofaa/entitylib/velocity/VelocityEntityLibPlatform.java
at line 20, the userLocaleProvider field is declared but not initialized,
risking a NullPointerException if accessed before being set. To fix this,
initialize userLocaleProvider with a default implementation similar to other
platforms or provide a safe fallback instance during declaration or in the
constructor to ensure it is never null when accessed.

Comment on lines +60 to +68
@Override
public @NotNull UserLocaleProvider getUserLocaleProvider() {
return userLocaleProvider;
}

@Override
public void setUserLocaleProvider(final UserLocaleProvider userLocaleProvider) {
this.userLocaleProvider = userLocaleProvider;
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

@NotNull annotation inconsistent with nullable field.

The getUserLocaleProvider() method is annotated with @NotNull but the field can be null since it's not initialized. This violates the annotation contract and could mislead callers.

Either initialize the field with a default value or remove the @NotNull annotation and add null checking where the provider is used.

🤖 Prompt for AI Agents
In
platforms/velocity/src/main/java/me/tofaa/entitylib/velocity/VelocityEntityLibPlatform.java
around lines 60 to 68, the getUserLocaleProvider() method is annotated with
@NotNull but the userLocaleProvider field is not initialized and can be null,
violating the annotation contract. To fix this, either initialize
userLocaleProvider with a default non-null value or remove the @NotNull
annotation from the getter and add null checks wherever userLocaleProvider is
used to handle potential null values safely.

Comment on lines +9 to +14
public class VelocityPlayerLocaleProvider implements UserLocaleProvider {
private final ProxyServer proxyServer;

public VelocityPlayerLocaleProvider(final ProxyServer proxyServer) {
this.proxyServer = proxyServer;
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add null validation and documentation.

The constructor lacks null validation and the class needs documentation to explain its purpose.

+import java.util.Objects;
+
+/**
+ * Velocity platform implementation of {@link UserLocaleProvider}.
+ * Retrieves player locales from the Velocity proxy server.
+ */
 public class VelocityPlayerLocaleProvider implements UserLocaleProvider {
     private final ProxyServer proxyServer;

     public VelocityPlayerLocaleProvider(final ProxyServer proxyServer) {
-        this.proxyServer = proxyServer;
+        this.proxyServer = Objects.requireNonNull(proxyServer, "proxyServer cannot be null");
     }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
public class VelocityPlayerLocaleProvider implements UserLocaleProvider {
private final ProxyServer proxyServer;
public VelocityPlayerLocaleProvider(final ProxyServer proxyServer) {
this.proxyServer = proxyServer;
}
import java.util.Objects;
/**
* Velocity platform implementation of {@link UserLocaleProvider}.
* Retrieves player locales from the Velocity proxy server.
*/
public class VelocityPlayerLocaleProvider implements UserLocaleProvider {
private final ProxyServer proxyServer;
public VelocityPlayerLocaleProvider(final ProxyServer proxyServer) {
this.proxyServer = Objects.requireNonNull(proxyServer, "proxyServer cannot be null");
}
// existing methods...
}
🤖 Prompt for AI Agents
In
platforms/velocity/src/main/java/me/tofaa/entitylib/velocity/VelocityPlayerLocaleProvider.java
around lines 9 to 14, add JavaDoc comments above the class to describe its
purpose clearly. Also, add a null check in the constructor for the proxyServer
parameter, throwing an appropriate exception if it is null to prevent potential
NullPointerExceptions later.

Comment on lines +16 to +19
@Override
public Locale locale(final UUID user) {
return proxyServer.getPlayer(user).map(Player::getEffectiveLocale).orElse(Locale.US);
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Consider method naming consistency and add null annotations.

The method should align with interface improvements and include proper null safety.

+    import org.jetbrains.annotations.NotNull;
+
     @Override
-    public Locale locale(final UUID user) {
+    public @NotNull Locale getUserLocale(@NotNull final UUID user) {
+        Objects.requireNonNull(user, "user cannot be null");
         return proxyServer.getPlayer(user).map(Player::getEffectiveLocale).orElse(Locale.US);
     }

Note: This assumes the interface method name is updated as suggested in the earlier review.

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In
platforms/velocity/src/main/java/me/tofaa/entitylib/velocity/VelocityPlayerLocaleProvider.java
around lines 16 to 19, rename the method from locale to getLocale to match the
updated interface naming convention. Additionally, add appropriate nullability
annotations such as @Nullable or @NonNull to the method signature and parameters
to ensure null safety and clarity about the method's contract.

@Tofaa2
Copy link
Owner

Tofaa2 commented Jul 21, 2025

Im contemplating the reason why this should be in EntityLib but im not opposed to it. LGTM in general before i merge can i ask what your usecase is.

@huanmeng-qwq
Copy link
Contributor Author

Im contemplating the reason why this should be in EntityLib but im not opposed to it. LGTM in general before i merge can i ask what your usecase is.

image

Similar to the one in the image, Argument actually returns a VirtualComponent, which will not participate in serialization nor be rendered by render. Therefore, I hope to support this kind of custom translate text component

@Tofaa2 Tofaa2 merged commit bff89d2 into Tofaa2:master Jul 21, 2025
2 of 3 checks passed
@huanmeng-qwq huanmeng-qwq deleted the feat/translation-render branch July 22, 2025 03:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants