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

feat(gatsby-plugin-manifest): add i18n, localization #13471

Merged

Conversation

CanRau
Copy link
Contributor

@CanRau CanRau commented Apr 18, 2019

Description

As introduced here #10250 I thought why not just update my fork and push it

So to use i18n you use the new manifests property and give it an array with all versions.

// in gatsby-config.js
module.exports = {
  plugins: [
    {
      resolve: `gatsby-plugin-manifest`,
      options: {
        manifests: [
          {
            name: `GatsbyJS`,
            short_name: `GatsbyJS`,
            start_url: `/de/`,
            regex: `^/de/.*`,
            language: `de`,
            background_color: `#f7f0eb`,
            theme_color: `#a2466c`,
            display: `standalone`,
          },
          {
            name: `GatsbyJS`,
            short_name: `GatsbyJS`,
            start_url: `/`,
            regex: `.*`,
            background_color: `#f7f0eb`,
            theme_color: `#a2466c`,
            display: `standalone`,
          },
        ],
      },
    },
  ],
}

The language prop works as a filename suffix, so the first array entry will write to manifest_de.webmanifest and as a default regex (which is not documented so far).

All manifests are written to the root of /public

It works so far, I'm not exactly sure about all coding styles or if my tests are sufficient, still not enough into testing (really have to get into it!!).

So please let me know if I can improve anything, I'm keen to learn.

Related Issues

Closes #10250

@KyleAMathews
Copy link
Contributor

Huh very cool! I love the idea of supporting i18n manifests!

Having both language and regex for selecting the language seems a bit cumbersome. Any reason for having both? Also the key name regex isn't overly obvious what it's for. A more verbose key name might be more self-documenting perhaps.

@CanRau
Copy link
Contributor Author

CanRau commented Apr 22, 2019

Kay agree on the naming 👍
The regex is to provide various styles of language differentiation but falls back to beginning of path like /en/path
In this case it's optional
I thought people might have another setup like path?lang=en even though it's usually not recommended as I understand

Any thoughts or ideas? We could provide only the first for now and see what feedback we get to start simple..so regex wouldn't be customizable only language has to be defined..
I'm open to other matching options and API 😃

@moonmeister moonmeister added topic: plugins status: awaiting author response Additional information has been requested from the author labels Apr 23, 2019
@moonmeister
Copy link
Contributor

@CanRau I love this idea as well. First question, how does the browser know which manifest to use? Second, have you put any thought into implementing this in a way that doesn't break the existing API? If so, is there a reason you didn't choose this method?

Thanks for sharing!

@moonmeister
Copy link
Contributor

Just read #10250 and saw your discussion around non-breaking API changes. Please expand on why you didn't follow that path if possible.

FYI: I know the manifest plugin currently blows up if you configure it multiple times. I believe this could be fixed but it's been a bit since I realized this so I don't remember what causes it. #12754 for ref

@CanRau
Copy link
Contributor Author

CanRau commented Apr 23, 2019

Not sure what is breaking in the proposed API? It's just adding some props, all existing tests pass without a problem. Um, maybe I'm missing something? Just realized the API I proposed in #10250 is indeed a little different, the first proposal wouldn't work because pluginOptions are always an object at least at this moment, the second proposal having multiple instances of the plugin seems more complicated, the proposal here in the PR is simpler and would easily allow one to define all manifests in another file. Think it's more complicated to determine which manifest to include in the <head/> maybe using gatsby's store could work don't know..here I already wrote about the new API

When you set it up as in the readme example it'll generate all manifests for all languages in the root of the project like /manifest_en.webmanifest which is happening here in gatsby-node.js if you've defined the new manifests prop as an array it'll create multiple manifests otherwise one, just like before

And here in gatsby-ssr.js it'll pick the right manifest from the manifests array based on the language and the regex which matches against the page pathname which looks like /en/awesome-page so that it sets the proper headComponent.

@moonmeister
Copy link
Contributor

moonmeister commented Apr 24, 2019

@CanRau Thanks for the detailed explanation. I just saw the manifests: [] and assumed that would break the existing API. But you've handled that well.

So you've given examples on how to not duplicate cod using Assign or rest/spread operators. This works well. I'm wondering if it'd be better to keep the shared settings in the options: {}. e.g.:

module.exports = {
  plugins: [
    {
      resolve: 'gatsby-plugin-manifest',
      options: {
        name: `GatsbyJS`,
        short_name: `GatsbyJS`,
        background_color: `#f7f0eb`,
        theme_color: `#a2466c`,
        display: `standalone`,
        manifests: [
          {
            
            start_url: `/de/`,
            regex: `^/de/.*`,
            language: `de`,
          },
          {
            start_url: `/`,
            regex: `.*`,
          },
        ],
      }
    }
 ]
}

This seems more consistent with the existing configuration and simpler to understand what's happening. Anything that is duplicated in the manifests array should override what's in the top level options. This seems like a less drastic change that is easier to convert to if your adding i18n to an existing manifest config.

@moonmeister moonmeister reopened this Apr 24, 2019
@moonmeister
Copy link
Contributor

Wrong button...

Copy link
Contributor

@moonmeister moonmeister left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good so far. mostly nit picks and then the issue of i18n of icons.

packages/gatsby-plugin-manifest/src/gatsby-node.js Outdated Show resolved Hide resolved
packages/gatsby-plugin-manifest/src/gatsby-ssr.js Outdated Show resolved Hide resolved
packages/gatsby-plugin-manifest/src/gatsby-ssr.js Outdated Show resolved Hide resolved
packages/gatsby-plugin-manifest/src/gatsby-node.js Outdated Show resolved Hide resolved
@CanRau
Copy link
Contributor Author

CanRau commented Apr 24, 2019

Thank you for your suggestions/comments @moonmeister 🙏
Any thoughts on @KyleAMathews' request: #13471 (comment)
And my proposals #13471 (comment) about config naming, especially the regex prop?

@moonmeister
Copy link
Contributor

moonmeister commented Apr 24, 2019

@CanRau I understand your reasoning. My thought is let's keep it simple. If using the path is best practice. then let's just build for that. If someone decides they really want to not use path they could contribute that functionality themselves. This keeps the API simpler and more approachable and only adds complexity if the community needs it.

If we do decide to keep this let's just make sure it' clearly documented that only one of the options is need. Or we maybe design it so it is a single option. Meaning someone can just type the path or a Regex...then the code determines what it is and uses it appropriately?

EDIT: I'm pretty neutral, leaning slightly towards simpler.

@CanRau
Copy link
Contributor Author

CanRau commented Apr 24, 2019

@CanRau Thanks for the detailed explanation. I just saw the manifests: [] and assumed that would break the existing API. But you've handled that well.

No worries, we all have a lot to do, all fine 👊 😉

Anything that is duplicated in the manifests array should override what's in the top level options. This seems like a less drastic change that is easier to convert to if your adding i18n to an existing manifest config.

I like it 👍 going to bed now, integrating it tomorrow

I'm open to dropping the regex altogether, as I think it seems path based seems the preferred by Google, at least over query params..

Meaning someone can just type the path or a Regex...then the code determines what it is and uses it appropriately?

Would love to know how you'd do that? I mean finding the proper manifest in gatsby-ssr.js works already like this, but the name suffix in both, how would you do this? Just out of curiosity 🤔 Cause I think just dropping this customization might be the best for now anyway, to have a smaller and simpler API.

@moonmeister
Copy link
Contributor

Would love to know how you'd do that? I mean finding the proper manifest in gatsby-ssr.js works already like this, but the name suffix in both, how would you do this? Just out of curiosity Cause I think just dropping this customization might be the best for now anyway, to have a smaller and simpler API.

Then let's just KIS (Keep it simple!) and eliminate regex. Using a single option to be one or the other would probably get complicated...but you could probably write a regex to determine if it was regex 🙄. It's a bad idea...just ignore me.

@moonmeister
Copy link
Contributor

Just realized we need to make sure this accounts for the use of pathPrefix

@LekoArts
Copy link
Contributor

Before merging this I want to discuss if this is actually the best approach: #10250 (comment)

@CanRau
Copy link
Contributor Author

CanRau commented Apr 24, 2019

Just realized we need to make sure this accounts for the use of pathPrefix

@moonmeister Think it's already using withPrefix in gatsby-ssr.js which should still work as I'm pretty sure I didn't break former behavior?!

Before merging this I want to discuss if this is actually the best approach: #10250 (comment)

Thanks for bringing this up @LekoArts, can't recall my tests and research exactly.

Not sure how I missed the lang property of manifests

Think it's interesting Google uses manifest.json whereas this from RealFaviconGenerator pointing to brought me to Mozilla where they explicitly state it should use the .webmanifest extension ^^

Pretty sure I've come to the current naming convention from some Stackoverflow but can't find it right now 🤔 think I tested my implementation on our website and it worked, providing the correct manifest depending on the language in pathname, but just tested Chrome though...

So should we follow the Chrome Webstore suggestion? Not even 💯 % sure it really applies to web-apps?
I mean we could "just" stuff the manifests in the appropriate language subfolder and don't add a suffix

Probably because of this Google web fundamentals I didn't realized the lang property, they're not mentioning it

And then it seems sooner or later people have to implement a beforeinstallprompt event listener themselves, any thoughts on this? Should we just explain this in the readme or provide some customizable/importable basic version?

Update maybe we go for manifest.json as well cause Google? 🤔

@moonmeister
Copy link
Contributor

So, I think we need to figure out what of this is actual spec and what of this is Google. Mozilla docs are likely to be closer to the spec. We should build this to enable any spec that exists. I can do more research for tomorrow, for now it's bed time.

@CanRau
Copy link
Contributor Author

CanRau commented Apr 24, 2019

Have a good rest then 😴 👍

Here's some discussion going on in w3c/manifest#676 but there's more to find w3c/manifest?q=i18n

@moonmeister
Copy link
Contributor

moonmeister commented Apr 24, 2019

Curiosity is the enemy of sleep:

https://www.w3.org/TR/appmanifest/#internationalization

My reading of this is "do what works". For static sites, the proposed seems a good method. Maybe just use the built in "lang" instead of "language".

I think both of @LekoArts links are for extension APIs and stores which don't apply, they're a different spec technically.

Also, I think event listeners are optional customizations...not required to add to home screen...don't quote me I could be wrong...but at least FF is like this.

@CanRau
Copy link
Contributor Author

CanRau commented Apr 24, 2019

Also, I think event listeners are optional customizations...not required to add to home screen...don't quote me I could be wrong...but at least FF is like this.

Might not be forever optional https://love2dev.com/blog/beforeinstallprompt/ and this right below the code block sounds reasonable to me

Success: you may want to wait before showing the prompt to the user, so you don't distract them from what they're doing. For example, if the user is in a check-out flow, or creating their account, let them complete that before interrupting them with the prompt.

Update: Another note on "add to homescreen" behavior

Kay I'm renaming language to lang now and include it in the manifest right?
And process the root manifest even if manifests array is defined correct?
Did I get it right that it might be interesting to always include lang? Should we add it to the docs?
How do we name manifests?

@moonmeister
Copy link
Contributor

Let's leave the event listeners to another PR but sounds like you could open an issue so we don't forget.

Yes.

Yes.

I wouldn't worry about adding it outside the l10n docs

Keep the .webmanifest extension as the spec uses this. I don't think it matters but no point in changing it.

CanRau and others added 10 commits June 25, 2019 02:04
Co-Authored-By: CanRau <cansrau@gmail.com>
language manifests in the `manifests` prop now merge top level options
as suggested here gatsbyjs#13471 (comment)
use option merging style in README

docs: change features as suggested here gatsbyjs#13471 (comment)
* rename `manifests` to `localize`
* rename `language` to `lang`
* include `lang` in manifest file
* merge root options and locales
* ensure root only merges if it has start_url provided
* always generate root options
* remove regex
* use start_url as matcher
* update docs & test
@moonmeister moonmeister force-pushed the feature/gatsby-plugin-manifest_i18n branch from 87e8921 to a938cba Compare June 24, 2019 18:07
@moonmeister
Copy link
Contributor

@freiksenet Alright, I think I've resolved that issue and added some basic caching to keep duplicate icons from being rebuilt multiple times. The caching made the existing tests do some weird things but I think I have everything passing in a valid way. This Should be ready to merge now.

@freiksenet
Copy link
Contributor

Thank you @moonmeister @CanRau!

@freiksenet freiksenet merged commit d93e478 into gatsbyjs:master Jul 2, 2019
@sidharthachatterjee
Copy link
Contributor

Published in gatsby-plugin-manifest@2.2.1

@CanRau CanRau deleted the feature/gatsby-plugin-manifest_i18n branch August 11, 2019 05:50
@CanRau
Copy link
Contributor Author

CanRau commented Aug 26, 2019

Thanks a lot for finalizing & shipping it you awesome people!! Thanks a lot! <3

wardpeet added a commit that referenced this pull request Sep 26, 2019
With the addition of the localize option in gatsby-plugin-manifest (#13471), multiple manifests can be generated and served depending on the path of the URL. While the correct manifest is served on initial page load, the link to the manifest is never updated even if the user navigates to a page that should include a different manifest.

Co-authored-by: Ward Peeters <ward@coding-tech.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
status: awaiting author response Additional information has been requested from the author
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[gatsby-plugin-manifest] internationalization (i18n)
7 participants