Skip to content

Language Translation Data Generation

Maksym Uimanov edited this page Feb 12, 2026 · 1 revision

Language Translation Data Generation

The Temporal API provides a comprehensive set of annotations for automatically generating translations for different languages during data generation. These annotations eliminate the need for manual JSON language file creation by programmatically registering translations for items, blocks, entities, and other registry objects.

Responsibilities / Purpose

  • Automates translation generation: Generates language JSON files without manual asset creation
  • Supports extensive languages: Covers 100+ languages and regional variants
  • Integrates with data generation: Works seamlessly with NeoForge's data generation system
  • Enables localization: Provides comprehensive internationalization support
  • Placeholder resolution: Supports dynamic translation placeholders for flexible text generation

How it works

  1. Annotation processing: The framework scans fields annotated with translation annotations
  2. Key generation: Creates translation keys based on object type and registry name
  3. Placeholder resolution: Processes translation values with placeholder resolvers
  4. Language registration: Registers translations for specified languages
  5. Data generation: During data generation, language JSON files are automatically generated

Single Language Annotations

@Translate_

Provides defined language translations for registry objects.

@TranslateAmericanEnglish("Example Ingot")
public static final DeferredItem<?> EXAMPLE_INGOT = ITEM_FACTORY.create("example_ingot");

Parameters:

  • id (optional, default: ""): Custom translation key override
  • value (required): Translation text (supports placeholders)
  • prefix (optional, default: ""): Text to prepend to translation key
  • suffix (optional, default: ""): Text to append to translation key

Multiple Language Annotation

@TranslateMultiple

Provides translations for multiple languages in a single annotation.

@AddCreativeModeTab(CreativeModeTabType.INGREDIENTS)
@GenerateBasicItemModel
@TranslateMultiple(
    americanEnglish = @TranslateAmericanEnglish("Banner Pattern"),
    britishEnglish = @TranslateBritishEnglish("Banner Pattern"),
    ...
)
public static final DeferredItem<?> EXAMPLE_BANNER_ITEM = ITEM_FACTORY.createBannerPattern("example_banner_pattern", ExampleBannerPatternTags.EXAMPLE);

Parameters:

  • americanEnglish: American English translations array
  • britishEnglish: British English translations array
  • polish: Polish translations array
  • ukrainian: Ukrainian translations array
  • french: French translations array
  • german: German translations array
  • spanish: Spanish translations array
  • simplifiedChinese: Simplified Chinese translations array
  • traditionalTaiwanChinese: Traditional Chinese (Taiwan) translations array
  • traditionalHongKongChinese: Traditional Chinese (Hong Kong) translations array
  • japanese: Japanese translations array
  • korean: Korean translations array
  • And 80+ more language variants...

Translation Key Generation

Translation keys are automatically generated based on the object type and registry name:

Item Translation Keys

item.modid.item_name

Block Translation Keys

block.modid.block_name

Entity Translation Keys

entity.modid.entity_name

Trim Pattern Translation Keys

trim_pattern.modid.pattern_name

Trim Material Translation Keys

trim_material.modid.material_name

Wolf Variant Translation Keys

entity.minecraft.wolf.variant.modid.variant_name

Painting Translation Keys

painting.modid.painting_name

Sound Translation Keys

subtitles.modid.sound_name

Custom Translation Keys

You can override the default translation key using the id parameter:

@TranslateAmericanEnglish(id = "custom.key.example", value = "Custom Translation")
public static final DeferredItem<?> EXAMPLE_ITEM = ITEM_FACTORY.create("example_item");

Prefix and Suffix Support

Add prefixes and suffixes to translation keys for organization:

@TranslateAmericanEnglish(
    value = "Example Item",
    prefix = "category.",
    suffix = ".name"
)
public static final DeferredItem<?> EXAMPLE_ITEM = ITEM_FACTORY.create("example_item");

This generates the key: category.item.modid.example_item.name

Multiple Translations per Object

You can provide multiple translations for the same object using arrays:

@TranslateMultiple(
    americanEnglish = {
        @TranslateAmericanEnglish("Banner Pattern"),
        @TranslateAmericanEnglish(value = "Example Banner Pattern", suffix = "desc")
    }
)
public static final DeferredItem<?> EXAMPLE_BANNER_ITEM = ITEM_FACTORY.createBannerPattern("example_banner_pattern", ExampleBannerPatternTags.EXAMPLE);

This generates:

  • item.modid.example_banner_pattern: "Banner Pattern"
  • item.modid.example_banner_pattern.desc: "Example Banner Pattern"

Supported Languages

The API supports over 100 languages and variants.

Translation Placeholder System

The Temporal API includes a sophisticated placeholder resolution system that allows translations to reference other translations dynamically. This system enables creating reusable and maintainable translation files.

TranslationPlaceholderResolver Interface

The core interface for placeholder resolution:

public interface TranslationPlaceholderResolver {
    String resolve(String key, String placeholder, Map<String, String> translationMap);
}

Parameters:

  • key: The current translation key being processed
  • placeholder: The placeholder text to resolve
  • translationMap: Complete map of available translations

KeyTranslationPlaceholderResolver

Resolves placeholders that are valid translation keys using the format {key.path}.

Pattern: ^([A-Za-z_-]+\.?)+[A-Za-z_-]+$

Usage:

@TranslateAmericanEnglish("Example Item")
public static final DeferredItem<?> EXAMPLE_ITEM = ITEM_FACTORY.create("example_item");

@TranslateAmericanEnglish("A {item.modid.example_item} with special properties")
public static final DeferredItem<?> SPECIAL_ITEM = ITEM_FACTORY.create("special_item");

Result: The placeholder {item.modid.example_item} will be replaced with "Example Item"

Features:

  • Validates placeholder format as a translation key
  • Looks up placeholder in translation map
  • Returns original placeholder if translation not found
  • Supports nested translation references

ThisTranslationPlaceholderResolver

Resolves placeholders using relative key references with the this keyword for dynamic key manipulation.

Pattern: ^this\d$|^\dthis$|^\dthis\d$|^this\$$|^\$this$|^\$this\$$

Usage Examples:

Basic this reference:

@TranslateAmericanEnglish("Example Category")
public static final DeferredItem<?> EXAMPLE_ITEM = ITEM_FACTORY.create("example_item");

// Translation key: item.modid.example_item.name
@TranslateAmericanEnglish("Item from {this}")
public static final DeferredItem<?> EXAMPLE_ITEM_NAME = ITEM_FACTORY.create("example_item_name");

With numeric modifiers:

// Translation key: item.modid.example_item
@TranslateAmericanEnglish("Uses {this0}")
public static final DeferredItem<?> EXAMPLE_ITEM = ITEM_FACTORY.create("example_item");

// Resolves to: Uses item.modid

With dollar sign modifiers:

// Translation key: item.modid.example_item
@TranslateAmericanEnglish("Part of {$this}")
public static final DeferredItem<?> EXAMPLE_ITEM = ITEM_FACTORY.create("example_item");

// Resolves to: Part of item.modid

Combined modifiers:

// Translation key: item.modid.example_item
@TranslateAmericanEnglish("Related to {1this2}")
public static final DeferredItem<?> EXAMPLE_ITEM = ITEM_FACTORY.create("example_item");

// Resolves to: Related to modid.example

Modifier Reference:

  • this: Current full key
  • thisN: Keep N keys from start (e.g., this1 keeps first key)
  • Nthis: Keep N keys from end (e.g., 1this keeps last key)
  • thisN: Keep first N keys (e.g., this2 keeps first 2 keys)
  • NthisM: Keep keys N through M (e.g., 1this2 keeps keys 1-2)
  • $this: Remove last key
  • $$this: Remove last two keys
  • this$: Remove first key
  • $this$: Remove first and last keys

TranslationValueResolver

Processes translation values and resolves all placeholders using registered resolvers.

public interface TranslationValueResolver {
    String PLACEHOLDER_REGEX = "\\{(.*?)}";
    
    String resolve(String key, String value, Map<String, String> translationMap, 
                   Iterable<TranslationPlaceholderResolver> placeholderResolvers);
}

SimpleTranslationValueResolver

Default implementation that processes placeholders in translation values.

Features:

  • Detects placeholders using regex pattern \{(.*?)}
  • Applies all registered placeholder resolvers
  • Maintains original text if placeholder cannot be resolved
  • Supports multiple placeholders in single translation

Placeholder Usage Examples

Basic Key Reference

@TranslateAmericanEnglish("Diamond Sword")
public static final DeferredItem<?> DIAMOND_SWORD = ITEM_FACTORY.create("diamond_sword");

@TranslateAmericanEnglish("A {item.modid.diamond_sword} with enchantments")
public static final DeferredItem<?> ENCHANTED_DIAMOND_SWORD = ITEM_FACTORY.create("enchanted_diamond_sword");

This Reference for Categories

@TranslateAmericanEnglish("Tools")
public static final DeferredItem<?> PICKAXE = ITEM_FACTORY.create("pickaxe");

// Translation key: item.modid.pickaxe
@TranslateAmericanEnglish("A tool from {this}")
public static final DeferredItem<?> IRON_PICKAXE = ITEM_FACTORY.create("iron_pickaxe");

Complex Placeholder Combinations

@TranslateAmericanEnglish("Example Mod")
public static final DeferredItem<?> EXAMPLE_ITEM = ITEM_FACTORY.create("example_item");

// Translation key: item.modid.example_item
@TranslateAmericanEnglish("Item from {$this} - {item.modid.example_item}")
public static final DeferredItem<?> DERIVED_ITEM = ITEM_FACTORY.create("derived_item");

Result: "Item from modid - Example Item"

Placeholder Resolution Process

  1. Detection: SimpleTranslationValueResolver scans for {placeholder} patterns
  2. Iteration: Each placeholder is processed through all registered resolvers
  3. Key Resolution: KeyTranslationPlaceholderResolver handles direct key references
  4. This Resolution: ThisTranslationPlaceholderResolver handles relative references
  5. Fallback: Unresolved placeholders remain as-is in the final translation

Integration with Translation Annotations

Placeholders work seamlessly with all translation annotations:

@TranslateMultiple(
    americanEnglish = @TranslateAmericanEnglish("A {item.modid.base_item} with upgrades"),
    britishEnglish = @TranslateBritishEnglish("A {item.modid.base_item} with upgrades"),
    french = @TranslateFrench("Un {item.modid.base_item} avec des améliorations")
)
public static final DeferredItem<?> UPGRADED_ITEM = ITEM_FACTORY.create("upgraded_item");

Best Practices

Use Key References for Reusable Text

@TranslateAmericanEnglish("Diamond")
public static final DeferredItem<?> DIAMOND_INGOT = ITEM_FACTORY.create("diamond_ingot");

@TranslateAmericanEnglish("{block.modid.diamond} Block")
public static final DeferredItem<?> DIAMOND_BLOCK = ITEM_FACTORY.create("diamond_block");

Use This References for Hierarchical Organization

@TranslateAmericanEnglish("Example Mod")
public static final DeferredItem<?> EXAMPLE_SWORD = ITEM_FACTORY.create("example_sword");

// Translation key: item.modid.example_sword
@TranslateAmericanEnglish("Weapon from {$this}")
public static final DeferredItem<?> EXAMPLE_BOW = ITEM_FACTORY.create("example_bow");

Combine Placeholders for Complex Text

@TranslateAmericanEnglish("Example Mod")
public static final DeferredItem<?> EXAMPLE_ITEM = ITEM_FACTORY.create("example_item");

@TranslateAmericanEnglish("Special {item.modid.example_item} from {$this}")
public static final DeferredItem<?> SPECIAL_ITEM = ITEM_FACTORY.create("special_item");

When to Use Placeholders

  • Reusable text: Common terms like material names, categories, or mod names
  • Hierarchical organization: Parent-child relationships in translation keys
  • Consistency: Ensuring the same term is used across multiple translations
  • Maintenance: Centralizing common text for easier updates
  • Complex descriptions: Building descriptions from multiple components

Available Resolvers

The API includes these built-in resolvers:

  • KeyTranslationPlaceholderResolver: Direct key reference resolution
  • ThisTranslationPlaceholderResolver: Relative key reference resolution
  • SimpleTranslationValueResolver: Default placeholder processing

These resolvers are automatically registered and available for use in all translation annotations.

When to use

  • Single language: Use specific language annotations for targeted localization
  • Multiple languages: Use @TranslateMultiple for comprehensive internationalization
  • Custom keys: Use id parameter for non-standard translation keys
  • Organization: Use prefix and suffix for translation key organization
  • Descriptions: Use multiple translations for main text and descriptions
  • Placeholders: Use placeholder system for reusable and maintainable translations
  • Hierarchical text: Use this references for organized translation structures

Extension Points

The annotation system integrates with Temporal API's metadata processing:

  • Automatic key generation: Creates appropriate translation keys based on object type
  • Placeholder resolution: Dynamic text substitution using multiple resolver strategies
  • Language file generation: Automatically generates JSON language files during data generation
  • Custom key support: Allows override of default translation keys
  • Comprehensive coverage: Supports all major Minecraft languages and many regional variants
  • Extensible resolvers: Custom placeholder resolvers for specialized text processing needs

Each annotation maps to a specific translation registration strategy that handles the translation generation logic, while the placeholder system provides powerful text composition capabilities, allowing for easy extension and customization of the translation system.

Clone this wiki locally