A new approach for JavaScript I18N and translator comments #67275
Replies: 1 comment 2 replies
-
Thanks for opening the discussion, @swissspidy! Personally, I think Approach B offers the best compromise. After all, this will only be a problem for projects that adopt React 19 and the React Compiler. It could be documented as a breaking change, and a requirement when migrating to using React 19 / React Compiler. Approach A would break many systems in ways that will be difficult to recover, while Approach C will require unsustainable migrations. Problems like this are exactly why we've been aiming for early adoption of React 19 / React Compiler in Gutenberg, and only when such problems are ironed out, with a proper migration path, we'd open them to the rest of the ecosystem and encourage the migration. From your Approach B examples, though, I'd lean towards The only thing I'd be cautious about is that if we have multiple uses of the same string with the same textdomain, they would use the same translation, even if they have different comments. I think that makes sense, because if folks want different translations, they could just use the context localization functions. This variety in behavior and localization needs is something that we'll also need to document well going further. |
Beta Was this translation helpful? Give feedback.
-
I am kicking off this discussion because it came up again as part of the work leveraging React Compiler (#66361), but this is not actually a new problem and has been on my mind for a long time.
For JavaScript i18n we use the same gettext-style API like in PHP, using the
__()
family of functions. Additional information for polyglots is often added with/* translators */
comments. On platforms like translate.wordpress.org, these are then extracted from the minified JS files using tools like WP-CLI. While this approach works well in PHP, it is not suitable for the modern JS landscape with minifiers, bundlers, and compilers.An issue early on in the development of Gutenberg was that
/* translators */
comments were removed from minified output. Luckily, webpack and Babel had options to preserve comments. Newer tools like React Compiler, esbuild, swc, etc., do not support preserving comments.Adding
/* translators */
comments is fragile because they are often not added directly preceding the__()
function call, but often on the line above or even further away. It's an easy mistake to make. In such a case, after minification the comment is often somewhere completely different, causing the string extraction tool to not pick it up. I recently fixed a lot of these issues in #66510.If we want to use state-of-the-art tooling, we need a better solution for translator comments.
Approach A: use source files for string extraction
If we only extract translator comments from the source files, it doesn't matter if they are missing from the minified files.
Pros:
@wordpress/i18n
requiredCons:
Because of the last point, I simply don't think this would be viable.
Approach B: Provide a slightly new JS API for translator comments
We could offer something like
__( 'Translate me', 'default', 'I am a translator comment' )
or__( { message: 'Translate me', domain: 'default', comment: 'I am a translator comment' } )
Pros:
Cons:
Approach c: Adopt a completely new JS i18n tooling
Something like MessageFormat / FormatJS would not only provide a better solution for translator comments, but also for supporting things like gendered translations.
Pros:
Cons:
Personally, right now I think approach B with
__( { message: 'Translate me', domain: 'default', comment: 'I am a translator comment' } )
is very reasonable and achievable.Curious to hear other thoughts.
Pinging relevant i18n folks:
@tyxla @SergeyBiryukov @ocean90 @jsnajdr
Beta Was this translation helpful? Give feedback.
All reactions