Verify dynamic locale support implementation#183
Conversation
|
@copilot Please look at the commit history on this issue and generate a detailed markdown description on the necessary steps to replicate in another sim for an agent to follow. Don't open a branch or a pull request, just comment below the description. |
Steps to Add Dynamic Locale Support to a PhET SimulationBased on the commit history for issue #179, here are the detailed steps to replicate dynamic locale support in another sim: Step 1: Enable YAML String Support (Commit f43ab9e)
Step 2: Convert Strings to String Properties (Commit dee9a29)Update all hardcoded string references to use string properties:
Step 3: Use Fluent String Access (Commit f86ac15)
Step 4: Add supportsDynamicLocale to package.json (Commit 560068c)"simFeatures": {
"supportsDynamicLocale": true,
// other features...
}
Step 5: Add maxWidth to All Text Nodes (Commit 900775d)
Step 6: Update String Patterns to Modern Format (Commit 859867c)Critical change: Update string patterns from legacy In strings files: - "pattern.0atomicScale": "{0} m (atomic scale)"
+ "pattern.atomicScale": "{{value}} m (atomic scale)"In code: // Before:
const scaleString = StringUtils.format( pattern0AtomicScaleStringProperty.value, '3.0 x 10<sup>-10</sup>' );
// After:
const scaleStringProperty = new DerivedStringProperty( [ atomicScalePatternStringProperty ], ( pattern: string ) => {
return StringUtils.fillIn( pattern, {
value: '3.0 x 10<sup>-10</sup>'
} );
} );Key changes:
Summary of Files to Update:
This ensures the simulation properly supports dynamic locale switching at runtime. Warning Firewall rules blocked me from connecting to one or more addresses (expand for details)I tried to connect to the following addresses, but was blocked by firewall rules:
If you need me to access, download, or install something from one of these locations, you can either:
|
|
@copilot The above documentation comment make sure to combine with what's already specified here: https://github.com/phetsims/phet-info/blob/main/doc/strings-i18n-yaml-fluent.md so an AI agent can go and do all the steps |
Comprehensive Guide: Adding Dynamic Locale Support to a PhET SimulationThis guide combines the commit history from issue #179 with the official PhET documentation to provide complete steps for an AI agent to implement dynamic locale support. PrerequisitesReview the official PhET documentation: Strings, i18n, YAML, and Fluent Step-by-Step ImplementationStep 1: Create the YAML String FileFrom repository root, run: grunt create-yamlThis converts your existing What this does: Automates initial conversion from legacy JSON format to YAML/Fluent format. Step 2: Generate Fluent ArtifactsRun: grunt modulify --targets=stringsThis generates:
Verify: Check that Step 3: Convert Strings to String PropertiesUpdate all hardcoded string references: // Before:
import RutherfordScatteringStrings from '../RutherfordScatteringStrings.js';
const label = new Text( RutherfordScatteringStrings.someString, { ... } );
// After:
import RutherfordScatteringStrings from '../RutherfordScatteringStrings.js';
const labelStringProperty = new Text( RutherfordScatteringStrings.someStringProperty, { ... } );Apply across: All view files (panels, screen views, nodes, etc.). Make sure variables that hold StringProperties also have that suffix. Example from commit dee9a29:
Step 4: Migrate to Fluent APIImport Fluent instead of Strings: // Before:
import RutherfordScatteringStrings from '../RutherfordScatteringStrings.js';
// After:
import RutherfordScatteringFluent from '../RutherfordScatteringFluent.js';Update references: // Before:
const labelStringProperty = RutherfordScatteringStrings.someStringProperty;
// After:
const labelStringProeprty = RutherfordScatteringFluent.someStringProperty;Fluent provides: FluentConstant for simple strings, FluentPattern for strings with placeholders. Example from commit f86ac15: Updated 14 files to use Fluent API throughout the simulation. Step 5: Add supportsDynamicLocale to package.jsonEdit package.json: {
"phet": {
"simFeatures": {
"supportsDynamicLocale": true,
// other features...
}
}
}Also run Step 6: Define and Apply maxWidth ConstantsIn your constants file (e.g., RSConstants.ts): const RSConstants = {
TEXT_MAX_WIDTH: 140, // Standard text width
PANEL_MIN_WIDTH: 230,
PANEL_MAX_WIDTH: 250,
// other constants...
};Apply maxWidth to ALL Text and RichText nodes: // Panel titles:
const titleText = new Text( titleStringProperty, {
font: RSConstants.PANEL_TITLE_FONT,
maxWidth: RSConstants.TEXT_MAX_WIDTH // ← Always add this
} );
// Slider labels (smaller):
const minLabel = new Text( minStringProperty, {
font: RSConstants.PANEL_TICK_FONT,
maxWidth: RSConstants.TEXT_MAX_WIDTH / 5 // ← Adjust as needed
} );
// Scale info (larger):
const labelText = new RichText( labelStringProperty, {
maxWidth: RSConstants.TEXT_MAX_WIDTH * 2 // ← Larger for scale labels
} );Step 7: Update String Patterns to Modern FormatCRITICAL CHANGE: Convert legacy patterns to Fluent format. In YAML String Files:# Before (legacy):
pattern.0atomicScale: '{0} m (atomic scale)'
pattern.0nuclearScale: '{0} m (nuclear scale)'
# After (modern Fluent):
pattern:
atomicScale: '{{value}} m (atomic scale)'
nuclearScale: '{{value}} m (nuclear scale)'Key changes:
In TypeScript Code:// Before (legacy):
import StringUtils from '../../../../phetcommon/js/util/StringUtils.js';
const scaleString = StringUtils.format(
pattern0AtomicScaleStringProperty.value,
'3.0 x 10<sup>-10</sup>'
);
const scaleInfoNode = new ScaleInfoNode( scaleString, width );
// After (modern Fluent with DerivedStringProperty):
import DerivedStringProperty from '../../../../axon/js/DerivedStringProperty.js';
import StringUtils from '../../../../phetcommon/js/util/StringUtils.js';
const atomicScaleStringProperty = new DerivedStringProperty(
[ atomicScalePatternStringProperty ],
( pattern: string ) => {
return StringUtils.fillIn( pattern, {
value: '3.0 x 10<sup>-10</sup>'
} );
}
);
const scaleInfoNode = new ScaleInfoNode( atomicScaleStringProperty, width );Or use FluentPattern API directly: // Using FluentPattern.createProperty():
const labelProperty = RutherfordScatteringFluent.pattern.atomicScale.createProperty( {
value: valueProperty // Can be a Property or static value
} );
// Or using FluentPattern.format() for one-time formatting:
const labelString = RutherfordScatteringFluent.pattern.atomicScale.format( {
value: '3.0 x 10<sup>-10</sup>'
} );Update Function Signatures if necessary:// Before:
public constructor( model: RSBaseModel, scaleString: string, ... ) {
// ...
}
// After:
import { TReadOnlyProperty } from '../../../../axon/js/TReadOnlyProperty.js';
public constructor( model: RSBaseModel, scaleString: TReadOnlyProperty<string>, ... ) {
// ...
}Important NotesYAML Syntax Rules:
Fluent Patterns:
Current Limitation:IMPORTANT: Fluent syntax should only be used for strings under the UI Logic vs Linguistic Logic:
Files to Update Summary
Verification Checklist
This comprehensive guide ensures complete implementation of dynamic locale support following PhET standards. |
The repository requires
supportsDynamicLocale: truein package.json per phetsims/joist#1005, now that the default is false.Verification Results
No code changes required. The simulation already has complete dynamic locale support:
supportsDynamicLocale: truepresent in package.json simFeatures (line 26)pattern.atomicScale: "{{value}} m (atomic scale)"RSConstants.TEXT_MAX_WIDTHKey Implementation Patterns
Panel titles:
Scale info with dynamic sizing:
The simulation is ready for publication with dynamic locale support.
Original prompt
💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.