Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Test Fluent.js for complex accessibility strings #992

Open
jessegreenberg opened this issue Nov 14, 2024 · 7 comments
Open

Test Fluent.js for complex accessibility strings #992

jessegreenberg opened this issue Nov 14, 2024 · 7 comments

Comments

@jessegreenberg
Copy link
Contributor

jessegreenberg commented Nov 14, 2024

After #990, we are going to try Fluent.js to support i18n for complex accessibility strings.

In this issue Ill track changes and progress. First, we are going to bring Fluent in as a dependency. Then, we are going to try it out with 3 sims. We are then going to test the strings with translators to get feedback.

EDIT: I have a growing list of branches in repos as we do this work. Collected in this coment: #992 (comment)

@jessegreenberg
Copy link
Contributor Author

The latest version of Fluent.js was not compatible with our preload system/sherpa which requires a standalone built file. We found a build in this format at https://www.npmjs.com/package/fluent. It is 5 years old.

We will want to figure out how we can get the latest version. For other POSE reasons, PhET is exploring how we can use a more standard way of importing dependencies. But if that isn't figured out, we will need to find a way to bundle a more recent version of Fluent so it can be used in sherpa.

@jessegreenberg
Copy link
Contributor Author

The above commits complete a first pass at using Fluent in ohms-law for accessibility strings.

jessegreenberg added a commit to phetsims/ohms-law that referenced this issue Nov 22, 2024
jessegreenberg added a commit to phetsims/chipper that referenced this issue Nov 22, 2024
jessegreenberg added a commit to phetsims/chipper that referenced this issue Nov 22, 2024
@jessegreenberg
Copy link
Contributor Author

jessegreenberg commented Nov 22, 2024

I am making a branch in chipper called fluent to hold preloads and utility classes that are supporting this work. See #1532.

jessegreenberg added a commit to phetsims/chipper that referenced this issue Nov 22, 2024
jessegreenberg added a commit to phetsims/ohms-law that referenced this issue Nov 22, 2024
jessegreenberg added a commit to phetsims/gravity-force-lab-basics that referenced this issue Nov 22, 2024
jessegreenberg added a commit to phetsims/gravity-force-lab-basics that referenced this issue Nov 25, 2024
@jessegreenberg
Copy link
Contributor Author

jessegreenberg commented Nov 25, 2024

GFL:B is proving to be too time consuming for this test because of the complicated string patterns. Strings are factored out and reassembled with code in a way that is good for English but is not friendly for i18n. We are going to switch to MaL instead.

@jessegreenberg
Copy link
Contributor Author

jessegreenberg commented Nov 25, 2024

List of repo branches so far to support this work:

  • chipper fluent - With classes and utility functions for working with fluent messages, and as Properties for dynamic locales.
  • ohms-law fluent - Sim implementation.
  • greenhouse-effect fluent - Sim implementation for molecules-and-light (molecules-and-light code lives in greenhouse-effect)
  • molecules-and-light fluent- Preloads for fluent need to be defined in its package.json, even though it pulls from greenhouse-effect.
  • perennial fluent - TypeScript in chipper requires Fluent files to be declared in this file.
  • scenery-phet - To test where we hold common code strings.
  • babel - This is where we will hold translations of the files. See Integrate Fluent.js with other string loading and modules #994.

jessegreenberg added a commit to phetsims/perennial that referenced this issue Nov 25, 2024
jessegreenberg added a commit to phetsims/greenhouse-effect that referenced this issue Nov 26, 2024
jessegreenberg added a commit to phetsims/greenhouse-effect that referenced this issue Nov 26, 2024
jessegreenberg added a commit to phetsims/scenery-phet that referenced this issue Nov 26, 2024
jessegreenberg added a commit to phetsims/greenhouse-effect that referenced this issue Nov 26, 2024
jessegreenberg added a commit to phetsims/greenhouse-effect that referenced this issue Nov 26, 2024
@jessegreenberg
Copy link
Contributor Author

The above commits complete a first pass at using Fluent in molecules-and-light for accessibility strings.

@jessegreenberg
Copy link
Contributor Author

jessegreenberg commented Dec 11, 2024

I met with @jonathanolson today to discuss Fluent.js support. We looked into the limitation described in #986 (comment) (attribute references cannot use variables which can create significant complexity in the Fluent.js patterns). We couldn't find a solution.

We thought this was important because of the following simple example string. All of this code (113 lines!!) is needed to translate the sentence "There are {{5}} {{yellow}} {{dogs}}" (brackets indicate a variable).

-dog = perro
-dog-plural = perros
-house = casa
-house-plural = casas
-table = mesa
-table-plural = mesas

-red-masculine = rojo
-red-feminine = roja
-red-masculine-plural = rojos
-red-feminine-plural = rojas

-black-masculine = negro
-black-feminine = negra
-black-masculine-plural = negros
-black-feminine-plural = negras

-white-masculine = blanco
-white-feminine = blanca
-white-masculine-plural = blanco
-white-feminine-plural = blanca

lang-noun = { $noun ->
[dog] { $quantity ->
[1] { -dog }
*[other] { -dog-plural }
}
[house] { $quantity ->
[1] { -house }
*[other] { -house-plural }
}
[table] { $quantity ->
[1] { -table }
*[other] { -table-plural }
}
*[fail] FAIL
}

noun-article = { $noun ->
[dog] { $quantity ->
[1] un
*[other] { $quantity }
}
[house] { $quantity ->
[1] una
*[other] { $quantity }
}
[table] { $quantity ->
[1] una
*[other] { $quantity }
}
*[fail] FAIL
}

-term = { $first ->
[foo] yes
[bar] no
*[fail] FAIL
}

color = { $noun ->
[dog] { $color ->
[red] { $quantity ->
[1] { -red-masculine }
*[other] { -red-masculine-plural }
}
[black] { $quantity ->
[1] { -black-masculine }
*[other] { -black-masculine-plural }
}
[white] { $quantity ->
[1] { -white-masculine }
*[other] { -white-masculine-plural }
}
*[fail] FAIL
}
[house] { $color ->
[red] { $quantity ->
[1] { -red-feminine }
*[other] { -red-feminine-plural }
}
[black] { $quantity ->
[1] { -black-feminine }
*[other] { -black-feminine-plural }
}
[white] { $quantity ->
[1] { -white-feminine }
*[other] { -white-feminine-plural }
}
*[fail] FAIL
}
[table] { $color ->
[red] { $quantity ->
[1] { -red-feminine }
*[other] { -red-feminine-plural }
}
[black] { $quantity ->
[1] { -black-feminine }
*[other] { -black-feminine-plural }
}
[white] { $quantity ->
[1] { -white-feminine }
*[other] { -white-feminine-plural }
}
*[fail] FAIL
}
*[fail] FAIL
}

sentence = { $quantity ->
[1] Es
*[multiple] Son
} { noun-article } { lang-noun } { color }

Consider the equivalent 6 lines of javascript:

const singular = quantity === 1;
const masculine = [ 'dog' ].includes( noun );
const nounString = { dog: 'perro', house: 'casa', table: 'mesa', street: 'calle' }[ noun ] + ( singular ? '' : 's' );
const colorString = { red: 'roj', black: 'negr', white: 'blanc', yellow: 'amarill' }[ color ] + ( masculine ? 'o' : 'a' ) + ( singular ? '' : 's' );
const string = `${singular ? 'Es' : 'Son'} ${singular ? (masculine ? 'un' : 'una') : quantity} ${nounString}`

We looked into a custom functions (a Fluent.js feature) to improve this. We hoped this would be something that a translator to directly get translations for variable terms and attributes. You can create your own function in a Fluent bundle like this:

    function CALL( ...args: any ) {

      // Do something with the provided term and its attributes to select the appropriate translations.
      // For example, look up a .gender attribute on the provided term and then return a string that
      // combines 
      console.log( args );
      return 'a string';
    };

    const bundle = new FluentRef.FluentBundle( locale, {
      functions: {
        CALL: CALL
      }
    } );

And the translator could use it like this:

-dog = perro
  .gender = masculine

-cat = gata
  .gender = feminine

-color-white =
    { $case ->
       *[feminine] blanca
        [masculine] blanco
    }

dog-description = The { $animal ->
  [DOG] { -dog}
  [CAT] { -cat }
} is { CALL($animal, color: -color-white) }

Unfortunately, the values passed to the custom function (like the value of color: -color-white in this case) are resolved to strings. We would need objects and attributes from the fluent file for this to be useful. For example, to look up the gender attribute on the provided term to select aSo this approach doesn't help us.

We talked about possibilities like

  1. Modifying Fluent.js to that it meets our needs.
  2. Creating our own library that can support our needs.
  3. Reaching out to Fluent.js community/devs to see if they have recommendations.

It is not clear how important this is. We haven't encountered this amount of complexity in the sims we have worked on so far (ohms-law, molecules-and-light, ph-scale-basics).

jessegreenberg added a commit to phetsims/ohms-law that referenced this issue Dec 16, 2024
jessegreenberg added a commit to phetsims/chipper that referenced this issue Dec 16, 2024
jessegreenberg added a commit to phetsims/greenhouse-effect that referenced this issue Dec 16, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant