-
-
Notifications
You must be signed in to change notification settings - Fork 861
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
Skip non-element VNode in interpolation #211
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for your PR! 👍
However, In CircleCI, Occurred error. 😞
Could you fix it?
Codecov Report
@@ Coverage Diff @@
## dev #211 +/- ##
==========================================
+ Coverage 96.88% 96.89% +0.01%
==========================================
Files 8 8
Lines 545 547 +2
==========================================
+ Hits 528 530 +2
Misses 17 17
Continue to review full report at Codecov.
|
Yes, I also noticed that unit tests fail. And I thought again, this is a bit complicated. As addressed in #210 , line breaks are considered as VNodes. Follow code produces 3 VNodes: two elements and the line break in between. <i18n path="msg" tag="div">
<strong>bold</strong>
<em>italic</em>
</i18n> However, following code has exactly the same VNodes parsed: the whitespace is a VNode too. <i18n path="msg" tag="div">
<strong>bold</strong> <em>italic</em>
</i18n> I think what VDom done is right, because it behaves similar as how browsers parse line breaks or contiguous whitespaces between elements. So the question shifts here: are the text nodes inside Before component interpolation this is very simple. All text interpolations are passed within an object to the But for component interpolation, it's not easy to answer. And current test cases are only designed for meaningful text, e.g. data binding. In my opinion, if the text can be determined ahead of runtime, it should be moved to the message string, even though it has the same appearance in different languages. So my current approach is to check both if (child.tag || child.text.trim()) {
params.push(child)
} This will skip all text content that consists of white spaces (general, not only |
Based on the PR, the last question still remains: as of <i18n path="msg" tag="div">
<strong>bold</strong>
<i18n-text>{{ plainText }}</i18n-text>
</i18n> Maybe another approach is to add a messages: {
en: {
msg: 'This is {0} and {1}.'
}
},
data: {
plainText: 'plain text'
} <i18n path="msg" tag="div" :places="{'1': plainText}">
<strong place="0">bold</strong>
</i18n> Renders: <div>This is <strong>bold</strong> and plain text.</div> For pure element interpolations, the <i18n path="msg" tag="div">
<strong>bold</strong>
<em>italic</em>
</i18n>
<i18n path="msg" tag="div">
<strong place="1">bold</strong>
<em place="0">italic</em>
</i18n> Renders: <div>This is <strong>bold</strong> and <em>italic</em>.</div>
<div>This is <em>italic</em> and <strong>bold</strong>.</div> I personally prefer this. It also behaves consistently with text interpolations of key value pairs. |
As I dig deeper into the source code, I found another issue that may be a barrier of implementing the
For messages interpolated with "numbers": messages: {
en: {
msg: 'This is {0} and {1}.'
}
} I could only pass an array: <div>{{ $t('msg', ['bold', 'italic']) }}</div> If I pass an object: <div>{{ $t('msg', {'0': 'bold', '1': 'italic'}) }}</div> The warning message appears, which is fine. However, the translation stops there. This is a bit too strict to the users. And it doesn't behave consistently with JavaScript. // These two expressions output the same result
Object.keys(['bold', 'italic'])
Object.keys({'0': 'bold', '1': 'italic'}) I've read some other i18n libs or components before, e.g. Dojo, Angular, etc. Under the hood, they all make list formatting syntax sugar of named formatting. To the users, this brings flexibility of formatting messages interpolated with "numbers". To the developers, reuse of such mechanism could be a lot easier to ship features like the "places" idea I proposed. |
Thank you for your fix and consideration!
Sorry, my poor documentation. 🙇
In about this, I don't know it, due to cannot imagine use-case. 💭❓
Oh! 💡That's good idea! |
If plain text is not under consideration, then I guess this PR is compatible with current design purpose.
const locales = {
en: {
info: 'You can {0} until 30 minutes from departure.',
refund: 'refund the ticket',
change: 'change your flight'
},
cn: {
info: '办理{0}手续的截止时间为起飞前 30 分钟。',
refund: '退票'
change: '改签'
}
} <i18n path="info" tag="p">
<a href="http://example.com">{{ $t('refund') }}</a>
</i18n> Changing the refund link is not a matter of message string any longer. Also, I can now make it just plain text, if the online service is not available yet. Whether the service is available is not a matter of message string either. Plus I could define more actions at ease. So this is really great! Let's go one step further. Say, for different actions the time limits vary. How do we do? const locales = {
en: {
info: 'You can {0} until {1} minutes from departure.',
refund: 'refund the ticket',
change: 'change your flight'
},
cn: {
info: '办理{0}手续的截止时间为起飞前 {1} 分钟。',
refund: '退票',
change: '改签'
}
} <i18n path="info" tag="p">
<a href="http://example.com">{{ $t('change') }}</a>
15
</i18n> Or maybe better: data: {
limit: {
refund: 30,
change: 15
}
} <i18n path="info" tag="p">
<a href="http://example.com">{{ $t('change') }}</a>
{{ limit.change }}
</i18n> Mixed content interpolations of element and plain text. But this has a tricky pitfall, what if the user wants to pass an empty string in his use case? How do we know it's by intention, or just another line break? We really couldn't.
With <i18n path="info" tag="p" :places="{'1': limit.change}">
<a place="0" href="http://example.com">{{ $t('change') }}</a>
</i18n> If we force the use of
I agree. It's a big architectural change. It does have necessity of thinking twice before move. |
Thank you for detailed explanation! I could understand about use-cases! Could you implement it please? If you can not implement, I hope you open the issues about that specification as docs. In this case, I merge this PR, after that I sometime implement it. |
It may not be very soon, but yep, I'll be glad to involve. |
Thank you for your issue registering! |
Please visit #210 for the details.
fix #210