-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
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
Add support for [Localazy] badge #5701
Conversation
|
Thanks for the PR @honzabilek4! I've pulled this up a couple times now planning to review, but the diff is on the larger side which complicates things a bit. I think this is largely driven by the number of distinct service class definitions and their respective tester files. Could you provide some additional context here on the badge(s) being added? I feel like that might make things easier for us to review and see if we couldn't potentially simplify the code while still achieving the same results. I've deployed a review app for this PR that can be used to include rendered badges from your branch if that helps For example, I feel like we could probably have a single class for the language progress badges, and just use a query parameter on the badge route that has three variants which control how the label is rendered (english, locale, locale name) So instead of https://shields-staging-pr-5701.herokuapp.com/localazy/lang-progress-loc/floating-apps/pt_BR We could just have something like the below for the three variants, all with a single class https://shields-staging-pr-5701.herokuapp.com/localazy/lang-progress/floating-apps/pt_BR?locale_display=loc https://shields-staging-pr-5701.herokuapp.com/localazy/lang-progress/floating-apps/pt_BR?locale_display=name |
Hi @calebcartwright, |
@calebcartwright I've updated the PR, please check it out 🙂 |
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.
Thanks for your contribution to Shields @honzabilek4! Overall this looks quite good, I've left a few comments and thoughts inline. 😉
] | ||
|
||
async handle({ projectId }) { | ||
const { message, label, color } = await this.fetch({ |
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.
Does this mean the Localazy API returns the colour itself? This seems a little odd to me, Shields.io generally decides it own colours through a set of conventions (e.g. colour gradients for percentages), I'm not sure what to think of an API imposing its own.
What do you think @calebcartwright ?
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.
Agreed. If there's a need to use a custom scale that'd probably be okay, but the colors used for those tiers should follow our conventions to be consistent with our offering.
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.
We return colour to quickly generate the badges on our side, though in this PR, it's always possible to override it as well as the other parameters.
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.
What is the convention here? The gradient would certainly make sense for single language progress, even though it's not that simple as some code coverage for example. The rest was supposed to be just an informational value, since 100% on the project doesn't mean that the localization process is necessarily finished.
|
||
const t = (module.exports = require('../tester').createServiceTester()) | ||
|
||
t.create('Localazy translation progress with langs') |
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.
Is there any specific reason why most of the tests used mocked responses? Apart from edge cases which are hard to encounter in real life, we generally prefer to hit the real service directly. This gives us much more confidence that the end-to-end flow is working correctly and allows us to be warned sooner rather than later when things unexpectedly change in upstream APIs.
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.
Okay, I can remove the mocks, it just depends on what do you want to test here.
color: Joi.string(), | ||
}) | ||
|
||
module.exports = class LocalazyBase extends BaseJsonService { |
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.
Nice extraction of common functionality. 👍🏻
|
||
const LocalazyBase = require('./localazy-base.service') | ||
|
||
module.exports = class LocalazyLangsSimple extends LocalazyBase { |
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.
I'm personally not a fan of this badge variant. It's almost the same as the LocalazyLangs
one, but less clear. The word "translated" is not quantifiable when used in isolation, which makes the badge somewhat confusing IMHO.
Maybe merge LocalazyLangsSimple
and LocalazyLangs
and use the noun form instead?
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.
Yeah, makes sense. 🙂
}, | ||
staticPreview: this.render({ | ||
message: '100%', | ||
label: 'Português (BR)', |
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.
I like the concept of displaying the language name in the language itself, that's a nice user experience. 👍🏻
static get documentation() { | ||
return `For more badges and detailed documentation of the params visit <a href="https://github.com/localazy/shields">localazy/shields</a> repository.` | ||
} | ||
|
||
static get keywords() { | ||
return ['l10n', 'i18n', 'localization', 'internationalization'] | ||
} |
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.
Could you convert these to static fields like the rest (category
, route
, etc.) please?
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.
Sure :)
const schema = Joi.object({ | ||
label: Joi.string(), | ||
message: Joi.string(), | ||
color: Joi.string(), | ||
}) |
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.
I'm a little surprised by this schema, as it has a very Shields.io feel to it 😄 Are we utilizing an API here that's been designed specifically with our schema in mind or does the native Localazy API just happen to have contracts structured this way?
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.
It's following the shields.io structure, so we can easily proxy the calls to your api and generate the badges on-the-fly.
https://connect.localazy.com/status/floating-apps?title=lang-loc-name&content=fr_CA
Same API is then used by the services here to fetch the raw data.
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.
It's following the shields.io structure, so we can easily proxy the calls to your api and generate the badges on-the-fly.
I'm confused by this. Could you elaborate on what you mean by "your api"?
If I was a user of the Localazy platform, and I wanted to integrate with it programmatically how would I go about doing that, what Localazy API(s) would I use?
What's currently proposed here is a bit concerning because it looks like the core aspects of the badge rendering are being controlled by the connect.localazy.com endpoint being used which I oppose.
Our core mission is providing 'concise, consistent, and legible' badges, and we do that by retrieving the raw data from the upstream system of record and using that data to produce the badges according to our specification and conventions. Ceding control of core default attributes like the badge label, message, and colors to some external endpoint is not going to be acceptable IMO.
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.
We've put the api together quickly for this purpose, so users can start using any badges before this gets merged.
https://github.com/localazy/shields
That's why the api copies the structure. We return these values directly for convenience and faster integration with shields.io.
We don't impose how the badge should look like, though we need to have some defaults. Users can always modify the overal look, title, colour etc. from within shields.io.
I can move the defaults directly to the repo if that's an issue.
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.
We don't impose how the badge should look like, though we need to have some defaults.
We have a suggested path on how we think we can best proceed, though I want to first do some contextual level setting that I think will be helpful.
I tend to view our service's badge offerings in two high level buckets:
- Our native/core badges that provide dyanmically updated badges that use raw data from various upstream tools/services/platforms, and do so in a way that's consistent
- Our build-your-own badge (BYOB) features that come in three flavors:
A. static badge builder (https://img.shields.io/badge/foo-bar-blue)
B. dynamic xml/json/yaml badge builder. this is similar to the static badge builder, except that the values can be set dynamically using xpath/jsonpath to query an arbitrary document instead of fixed/hard-coded
C. Endpoint badges (https://shields.io/endpoint / Announcing the Endpoint badge (beta) #2838) I like to think of this as a more powerful/flexible extension of the dynamic badge offering
That first bucket is the core of what we do, and is a large part of why Shields exists in the first place (more historical background here). We ensure that regardless of which platform/service is in use that the badges are consistent, both in specification and in presentation of information such as metrics and percentages, and status text like the result of a build. In order to be able to provide that consistency across our native badge offerings, we have to control core attributes of those badges we're providing which includes things like the defaults and text, color, etc. This is how we're able to provide a standard build status badge regardless of whether a user is using CI Service Foo or CI Service Bar, and the same holds true for other types of badges like code overage or localization status/progress.
Yes, we do support some opt-in customization options that our users can utilize should they choose to override the defaults, but we still have to ensure that the defaults are consistent across our platform. If Shields were to incorporate a native/core badge but not have control over those core attributes then we'd no longer be able to enforce and ensure that consistency and could quickly and easily end up in a place where our native badges are directly violating our own badge specification
Ultimately the challenge with this PR in it's current state is that it's proposing adding native/core badges but doing so in the BYOB fashion which just isn't compatible. We can't add a native badge that has the label, message, and color set by some external endpoint that we have no insight into nor control over.
We'd love to collaborate with you all and be able to get Localazy incorporated in our native badge offering, though we'll need to pivot a bit to make that happen. The next step to achieving that would be switching the service class implementation to utilize a Localazy API endpoint that directly provides the raw localization progress data. I'm unclear on whether such an endpoint exists yet, but I believe @PyvesB had some suggestions for a contract if not. I also believe that such an endpoint is beneficial above and beyond badges to allow Localazy users to have an API option to interact with the platform indepenent of a badge-specific focus.
If such an API doesn't yet exist then we can also work on helping with the implementation on the Shields side to integrate a native badge if you are willing to tackle the API implementation side.
I hope this helps, but please let us know if you have any questions!
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.
Hello @calebcartwright,
Thank you for thorough explanation! I know it can be tedious to maintain an open source project like this :)
I think I'll start with exploring the capabilities of our own API and update you on the progress.
I don't have any other questions generally.
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.
From the point of view of a user of the API, I can picture two endpoints:
- one endpoint requiring a project ID, which would return a response similar to the following:
{
"schemaVersion": 1,
"translationProgress": 0.96,
"translations": 5
}
- one endpoint requiring a project ID and a language code, which would return a response similar to the following:
{
"schemaVersion": 1,
"translationProgress": 0.97,
"languageName": "French",
"nativeLanguageName": "Français"
}
This would allow Shields.io to be able to control how it uses the data returned by Localazy and ensure consistency with other badges it offers, but it would also allow other consumers of the API to easily make use of it in different ways. 👍🏻
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.
Thanks for your suggestions. We'll do an update of our API and I'll get back to the PR as soon as possible.
Given that it's been a while, I'm going to go ahead close this pull request. Feel free to reopen it if you get a chance to look into it again, we would still be very keen to see Localazy badges added to Shields.io at some point! As a reminder, our thoughts on a way forward were summarised in #5701 (comment) and #5701 (comment). Thanks again for your interest in the Shields.io project! |
Closes #5670