Comments (27)
Yes, this is a good point — the story around fallbacks for the message formatting is not something that we've fully flushed out. But the fallbacks will work correctly for Number and Date/Time formatting, as those end up delegating to the built-in Intl
APIs
from formatjs.
Would you accept a patch to add an option to make getIntlMessage return "" when the message is not found instead of throwing? This would just be a stopgap until a proper fallback solution could be fleshed out.
from formatjs.
@pselden and I just started chatting about this on IRC.
Might be nice to have fallback strategy configurable at create time. undefMesg: 'throw'
would work as today, : {kind:'log', fallback: '['fr-FR'], default: 'foo'}
would allow error messages to console, pull from French if possible, and return a fixed string if not (default to en-US and empty string if not provided respectively,) {kind:'ignore',...}
would behave like 'log'
but without the console behavior, and undefined
would act like throw to keep old code from breaking.
Another nice thing about that approach is it's easy to extend if other behavior is needed.
from formatjs.
I would be willing to do this if it seemed sensible to people upstream
from formatjs.
@StoneCypher I don't follow what you're suggesting.
@pselden I don't think having silent "errors" — the case of an empty string — is the right idea.
Imagine a label for a button, in English that's "Save", but you're rending the page in French and you don't have a translation for that message. If the fallback strategy was to insert ""
as the button label, then you'd unknowingly be making the page unusable to the French user.
What we've recommended teams do in the past is have their build system merge the collection of translated strings with the default locale strings so that there's a value for every message ID, even if it's in a different language. In the example above, that page, rendered in French, would simply have an English "Save" label in the button.
We'd like to expand on this idea to make it easier to handle fallback string messages in apps. But I'm in favor of having explicit errors rather than "succeeding" silently which would unknowingly make the page unusable.
from formatjs.
@ericf I'm suggesting that the library be configurable at instantiation to let the developer choose the desired behavior, and recommending a mechanism theretowards. I'm also recommending a set of defaults which models what I believe you're suggesting as primary behavior, which I agree is correct for most cases, and which will maintain current behavior if configuration isn't added.
There are cases where you actually do want it to come back with a default string if no translation is provided. One example is the way Microsoft helps developers find translatable strings in apps: their system has a dummy language which returns text with strike-through characters over it, so that you can see visually what isn't handled yet.
from formatjs.
Guys, loading the messages in fr
and in en
for some users just to have a fallback mechanism is not realistic for production system. as @ericf mentioned, this is suppose to happen during the build process where you have the domain of locales that your application is suppose to support, and you have all messages in all language that you can preprocess (we call this completion process) to produce a valid list of messages that are required by your application for each supported language, this will guarantee that the "save" button (from @ericf's examples) will alway have a message that can be rendered accordingly.
We will work on providing guidance and probably a set of tools to support this use-case.
from formatjs.
... also, if you really want to implement a runtime fallback, u just need to create a shim for the formatMessage
helper, to massage the message before propagating it into the real formatMessage
implementation.
from formatjs.
k
from formatjs.
@ericf I also don't think providing empty strings is the way to go. However, in the Java world the accepted and imho best solution is to have a flag that allows you to configure message processing so that in stead of an exception, the requested key is returned (e.g. 'ui.button.save'). Having an application fail completely just because of a missing text imho is ridiculous.
from formatjs.
@mschipperheyn Agree completely, we are going to have to run a fork for now, see #56
from formatjs.
@Dakuan, @mschipperheyn, I like the example of the "Save" button from @ericf, and a console.log just does not make the cut for us. The reality is simple, if you throw, and you provide a way for people to prevent that by implementing something custom, everyone has the ability to do what they want. But if we warn instead, what about those who want to enforce very strict rules, like we do at Yahoo?
from formatjs.
@caridy I'd suggest that the permissive behaviour should be the default (to make the lib friendly to work with) and for the strict behaviour to be an option or override...
from formatjs.
It really depends if you want something aligned with how you guys work internally or something that's going to be friendly enough for us mortals to use. I think it would be a shame if you went for the 1st option.
Sorry to bang on! I really am extremely grateful that all this is available at all 💐
from formatjs.
Not sure if it will be useful at all to this discussion, but here is what I came up with for providing fallbacks for each locale (uses gulp).
https://gist.github.com/pselden/093965d29fc95ec7026b
I decided to fall back to en as a last resort to avoid crashing the app for non-translated languages.
from formatjs.
@pselden that's a good starting point for a fallback mechanism. At yahoo, we also do fallback at the message level, saying: you might have fr.json
, but a missing SAVE
message within in, which is a new entry in en.json
, and should be propagated, specially if you have a separate tool to consume en.json
to produce all the other files based on those entries.
from formatjs.
If you want to be strict, be strict. That's why we should havê a global option to handle this strictness. All it would do is return provided key in stead of throw error. This seems like a reasonable approach that satisfies everyone. Shame to have to have to fork for this. Look at Java, this is totally standard
from formatjs.
@mschipperheyn and Rails...
from formatjs.
@caridy If I understand what you're saying correctly, that's what this does (via gulp-multi-extend).
Anything from the more specific level will override the less specific level, but missing entries get filled in from the less specific levels. So a missing key in fr-FR.json will be filled by fr.json. A missing key in fr.json will be filled by en.json.
Example:
//fr-CA.json
{
"greeting": "Ca va?"
}
// fr.json
{
"greeting": "Bonjour!",
"goodbye": "Au revoir"
}
// en.json
{
"greeting": "Hi",
"goodbye": "Bye!",
"shout": "HEY!"
}
// becomes
//fr-CA.json
{
"greeting": "Ca va?",
"goodbye": "Au revoir",
"shout": "HEY!"
}
// fr.json
{
"greeting": "Bonjour!",
"goodbye": "Au revoir",
"shout": "HEY!"
}
// en.json
{
"greeting": "Hi",
"goodbye": "Bye!",
"shout": "HEY!"
}
from formatjs.
@pselden awesome!
@mschipperheyn alright, I will take this conversation offline with some folks, and let's see what comes from that, no promises. /cc @ericf
from formatjs.
@mschipperheyn thanks for the note about Java's behavior.
@pselden @Dakuan we all have the same goals here, to provide a fallback mechanism for messages. As it's been mentioned, we're starting off strict because we don't want things to fail silently. The more comprehensive fallback solution we want to provide will take a look at the whole picture to come up with the best way we can to solve the fallback case.
from formatjs.
Respectfully, something failing in production seems like a worst case to me. The other i18n systems I've worked with have all either provided fallback stubs, provided an explicit fallback instance, allowed the developer to specify a language as the last case language, or at a minimum provided the lookup key as the translatable text.
Microsoft's implementation in particular is amusing: they will zalgo your text (I'm not kidding) so that you can see the problem.
from formatjs.
Respectfully, something failing in production seems like a worst case to me.
@StoneCypher something will always fail in production. As mentioned in this thread we want to build a comprehensive solution. Before we have that solution we don't want to swallow errors because that would be lossy and leave developers in the dark about where the issue is.
from formatjs.
@ericf Choosing to cause exceptions when other paths are available seems like a worst case to me. I am also not aware of other i18n library vendors who have chosen faulting over trying to continue.
I don't think there's actually a need to swallow errors. It's relatively straightforward to, for example, provide a function which can be relied on to ping a server back home to say "oh actually there was an error." A great number of services exist to this end.
I believe that it is a false dichotomy to suggest that causing a web application to fail is the only way around losing information that there was a fault. Most web systems in production do not work this way (though Yahoo! Mail frequently dies on these grounds, which is one of the most frustrating things about being a Yahoo! Mail user.)
However, most other systems, both web and otherwise, make a best effort to continue service, and generally do not terminate under non-severe conditions.
My opinion is that most people would not actually find it reasonable for a web property to fail in production under user onus merely because a build system somewhere neglected to warn a developer that the label for a tab had been overlooked.
My strongly held opinion is that choosing to fail the user as the primary mechanism of aggregating defect data is a problematic choice. Users should not be QA. Faults are not, I believe, a responsible method of defect location. There are no shortage of other options.
Developers need not be in the dark in order to deliver a reliable end user experience.
from formatjs.
Since you seemed to appreciate the Java example, I'll point out that Microsoft's web setup has no trouble aggregating fault data from all Microsoft store applications simultaneously (a rather larger contingent than the web visitors to major properties, I believe.) They do not choose the "fault so that we find out there's a problem" approach.
Their model is admirable. Even the smallest of developers gets telemetry with literally zero effort, and the applications continue after a fault, quite frequently user entirely unaware.
As far as i18n goes, all I can say is that the baseline Windows XLIFF implementation and the older .res implementation explicitly handle this; the SDL tools explicitly handle this; Sun/GNU .po explicitly handles this; the Java .properties implementation explicitly handles this; .TM, .UNI, and .TF explicitly handle this. Indeed, the only major internationalization format that I'm aware of that does not handle this is Apple's, which also doesn't do things like inset variables, pluralization, etc.
As far as I know, every major translation system chooses to make tools like these available.
Maybe you want faults in production. That's cool. A mechanism which allowed those of us who do not want that to continue, however, would be greatly appreciated. Many developers feel that faults which are preventable in production are unacceptable, and should be avoided at nearly any cost.
Those, in combination with that the described costs (eg losing awareness) are relatively straightforwardly mitigated, suggest that possibly a developer chosen route might be appreciated.
Thanks for hearing me out.
from formatjs.
@StoneCypher I'm locking this thread as this discussion is getting way out scope and going in circles. I've stated numerous times that we want to revamp how to help people deal with fallback locales and strings. This thread is about a completely optional convenience method — you should simply not call it!
from formatjs.
See: #162
from formatjs.
Related Issues (20)
- @formatjs/intl-numberformat @ 8.9.0 -> 8.10.0 breaks Chrome 104 HOT 1
- cli-lib: onMsgExtracted never gets called HOT 1
- Update translation of 'last year' for Swedish locale HOT 1
- @formatjs/cli-lib is not an ESM module HOT 1
- formatMessage with ICU behave different then formatNumber HOT 2
- [@formatjs/intl Error MISSING_DATA] should be a warning not an error HOT 3
- [@formatjs/intl-durationformat] package.json deprecation warning HOT 2
- @formatjs/intl-messageformat, 10.5.0: Plural rules aren't applied correctly HOT 2
- @formatjs/intl-numberformat/polyfill: roundingIncrement seems to be a no-op HOT 3
- [docs] Rich Text Formatting example doesn't work HOT 2
- Polyfill.io has been sold to a weird Chinese company and should no longer be recommended HOT 1
- chore: update tzdata to 2024a
- INVALID_TAG when parsing regular HTML tag with attribute HOT 1
- Can't catch error HOT 1
- Feature request: allow units greater than `day` in `FormattedRelativeTime` with `updateIntervalInSeconds` to be picked HOT 2
- It's incredibly slow on lower end Android devices HOT 2
- Intl.Segmenter: isWordLike does not match Node.js and browsers HOT 2
- @formatjs/intl-locale/polyfill-force TypeError: Error uninitialized locale at Locale2.getWeekInfo HOT 3
- .formatMessage is not working when provided messages has object with `type: 1` HOT 8
- Extract does not work on vue template since vue 3.4.0 HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from formatjs.