Description
Both slash stripper and internationalization plugins need to mash up so as to meet both common SEO and multilingual requirements. The ordering of the plugins in this case is important. If trailing slashes is first the browser URL is more correct but SEO is potentially dinged.
For best results, internationalization should follow stripper. Did not realize that the plugins were order sensitive in gatsby-config.js. As long as the URL has at least two levels, this is fairly close but may still have the trailing slash.
Steps to reproduce
- Begin with the "my-blog-starter"
gatsby new my-blog-starter https://github.com/gatsbyjs/gatsby-starter-blog
cd my-blog-starter
- Install the "gatsby-plugin-remote-trailing-slashes"
npm install --require gatsby-plugin-remove-trailing-slashes
- Update gatsby-config.js
'gatsby-plugin-remove-trailing-slashes',
{
resolve: `gatsby-plugin-intl`,
options: {
// language JSON resource path
path: `${__dirname}/src/intl`,
// supported language
languages: [`en`, `ko`, `de`],
// language file path
defaultLanguage: `en`,
// option to redirect to `/en` when connecting `/`
redirect: true,
},
- Add translation files de.json, en.json, and ko.json to src/intl directory taking from these file at the following URL:
https://github.com/wiziple/gatsby-plugin-intl/tree/master/examples/gatsby-starter-default-intl/src/intl.
- Update the main project's index.js file as follows to include international text:
import React from "react"
// TKTKTK
// import { Link, graphql } from "gatsby"
import { graphql } from "gatsby"
import { FormattedMessage, Link, injectIntl } from "gatsby-plugin-intl"
import Bio from "../components/bio"
import Layout from "../components/layout"
import SEO from "../components/seo"
import { rhythm } from "../utils/typography"
class BlogIndex extends React.Component {
render() {
const { data } = this.props
const siteTitle = data.site.siteMetadata.title
const posts = data.allMarkdownRemark.edges
// TKTKTK
const intl = this.props.intl
const intlTitle = intl.formatMessage({ id: "welcome" });
return (
<Layout location={this.props.location} title={siteTitle}>
<SEO title="All posts" />
<h1>{intlTitle}</h1>
<h1><FormattedMessage id="title" /></h1>
<h1><FormattedMessage id="hello" /></h1>
<Bio />
{posts.map(({ node }) => {
const title = node.frontmatter.title || node.fields.slug
return (
<div key={node.fields.slug}>
<h3
style={{
marginBottom: rhythm(1 / 4),
}}
>
<Link style={{ boxShadow: `none` }} to={node.fields.slug}>
{title}
</Link>
</h3>
<small>{node.frontmatter.date}</small>
<p
dangerouslySetInnerHTML={{
__html: node.frontmatter.description || node.excerpt,
}}
/>
</div>
)
})}
</Layout>
)
}
}
// TKTKTK
// export default BlogIndex
export default injectIntl(BlogIndex)
export const pageQuery = graphql`
query {
site {
siteMetadata {
title
}
}
allMarkdownRemark(sort: { fields: [frontmatter___date], order: DESC }) {
edges {
node {
excerpt
fields {
slug
}
frontmatter {
date(formatString: "MMMM DD, YYYY")
title
description
}
}
}
}
}
`
- Update the main project's blog-post.js file as follows to include international text:
import React from "react"
// TKTKTK
// import { Link, graphql } from "gatsby"
import { graphql } from "gatsby"
import { FormattedMessage, Link, injectIntl } from "gatsby-plugin-intl"
import Bio from "../components/bio"
import Layout from "../components/layout"
import SEO from "../components/seo"
import { rhythm, scale } from "../utils/typography"
class BlogPostTemplate extends React.Component {
render() {
const post = this.props.data.markdownRemark
const siteTitle = this.props.data.site.siteMetadata.title
const { previous, next } = this.props.pageContext
// TKTKTK
const intl = this.props.intl
const intlTitle = intl.formatMessage({ id: "welcome" });
// const intlTitle = 'fubar'
return (
<Layout location={this.props.location} title={siteTitle}>
<SEO
title={post.frontmatter.title}
description={post.frontmatter.description || post.excerpt}
/>
<h1>{intlTitle}</h1>
<h1><FormattedMessage id="title" /></h1>
<h1><FormattedMessage id="hello" /></h1>
<h1>{post.frontmatter.title}</h1>
<p
style={{
...scale(-1 / 5),
display: `block`,
marginBottom: rhythm(1),
marginTop: rhythm(-1),
}}
>
{post.frontmatter.date}
</p>
<div dangerouslySetInnerHTML={{ __html: post.html }} />
<hr
style={{
marginBottom: rhythm(1),
}}
/>
<Bio />
<ul
style={{
display: `flex`,
flexWrap: `wrap`,
justifyContent: `space-between`,
listStyle: `none`,
padding: 0,
}}
>
<li>
{previous && (
<Link to={previous.fields.slug} rel="prev">
← {previous.frontmatter.title}
</Link>
)}
</li>
<li>
{next && (
<Link to={next.fields.slug} rel="next">
{next.frontmatter.title} →
</Link>
)}
</li>
</ul>
</Layout>
)
}
}
// TKTKTK
// export default BlogPostTemplate
export default injectIntl(BlogPostTemplate)
export const pageQuery = graphql`
query BlogPostBySlug($slug: String!) {
site {
siteMetadata {
title
author
}
}
markdownRemark(fields: { slug: { eq: $slug } }) {
id
excerpt(pruneLength: 160)
html
frontmatter {
title
date(formatString: "MMMM DD, YYYY")
description
}
}
}
`
- From the main project directory, execute the following command to start Gatsby:
clear && rm -rf .cache public && gatsby develop
Expected and Actual result
When order in gatsby-config.js:
- gatsby-plugin-intl
- gatsby-plugin-remove-trailing-slashes
http://localhost ==>
http://localhost/en/ ==>
Actual: http://localhost/en/en/ with English text
Expected: http://localhost/en with English text
http://localhost/ ==>
http://localhost/en/ ==>
Actual: http://localhost/en/en/ with English text
Expected: http://localhost/en with English text
http://localhost/de ==>
Actual: http://localhost/en/de with English text
Expected: http://localhost/de with German text
http://localhost/de/ ==>
Actual: http://localhost/en/de/ with English text
Expected: http://localhost/de with German text
http://localhost/my-second-post ==>
Actual: http://localhost/en/en/my-second-post with English text
Expected: http://localhost/en/my-second-post English text
http://localhost/my-second-post/ ==>
Actual: http://localhost/en/en/my-second-post/ with English text
Expected: http://localhost/en/my-second-post with English text
http://localhost/de/my-second-post ==>
Actual: http://localhost/en/de/my-second-post with English text
Expected: http://localhost/de/my-second-post with German text
http://localhost/de/my-second-post/ ==>
Actual: http://localhost/en/de/my-second-post/ with English text
Expected: http://localhost/de/my-second-post with German text
When order in gatsby-config.js:
- gatsby-plugin-remove-trailing-slashes
- gatsby-plugin-intl
http://localhost ==>
http://localhost/en/ ==>
Actual: http://localhost/en/en/ with English text
Expected: http://localhost/en with English text
http://localhost/ ==>
http://localhost/en/ ==>
Actual: http://localhost/en/en/ with English text
Expected: http://localhost/en with English text
http://localhost/de ==>
Actual: http://localhost/en/de with English text
Expected: http://localhost/de with German text
http://localhost/de/ ==>
Actual: http://localhost/en/de/ with English text
Expected: http://localhost/de with German text
http://localhost/my-second-post ==>
Actual: http://localhost/en/my-second-post with English text
Expected: Successful URL with English text
http://localhost/my-second-post/ ==>
Actual: http://localhost/en/my-second-post/ with English text
Expected: http://localhost/en/my-second-post with English text
http://localhost/de/my-second-post ==>
Actual: http://localhost/de/my-second-post with German text
Expected: Successful URL with German text
http://localhost/de/my-second-post/ ==>
Actual: http://localhost/de/my-second-post/ with German text
Expected: http://localhost/de/my-second-post with German text
Only gatsby-plugin-intl enabled in gatsby-config.js:
http://localhost ==>
Actual: http://localhost/en/ with English text
Expected: Successful URL with English text
http://localhost/ ==>
Actual: http://localhost/en/ with English text
Expected: Successful URL with English text
http://localhost/de ==>
Actual: http://localhost/de with German text
Expected: Successful URL with German text
http://localhost/de/ ==>
Actual: http://localhost/de/ with German text
Expected: Successful URL with German text
http://localhost/my-second-post ==>
Actual: http://localhost/en/my-second-post with English text
Expected: Successful URL with English text
http://localhost/my-second-post/ ==>
Actual: http://localhost/en/my-second-post/ with English text
Expected: Successful URL with English text
http://localhost/de/my-second-post ==>
Actual: http://localhost/de/my-second-post with German text
Expected: Successful URL with German text
http://localhost/de/my-second-post/ ==>
Actual: http://localhost/de/my-second-post/ with German text
Expected: Successful URL with German text
Errata
Maybe these two plugins would benefit from being combined together. The addition of the stripping slashes feature into international would seem pretty straight forward and might result in better performance.
Tomorrow, I plan to run the tests with just international. I will update with my findings. Updated.
Environment
System:
OS: macOS 10.14.5
CPU: (8) x64 Intel(R) Core(TM) i7-7920HQ CPU @ 3.10GHz
Shell: 5.0.2 - /usr/local/bin/bash
Binaries:
Node: 10.15.2 - /usr/local/bin/node
Yarn: 1.15.2 - ~/.yarn/bin/yarn
npm: 6.9.0 - /usr/local/bin/npm
Languages:
Python: 2.7.10 - /usr/bin/python
Browsers:
Chrome: 74.0.3729.169
Safari: 12.1.1
npmPackages:
gatsby: ^2.7.5 => 2.7.5
gatsby-image: ^2.1.2 => 2.1.2
gatsby-plugin-feed: ^2.2.1 => 2.2.1
gatsby-plugin-google-analytics: ^2.0.20 => 2.0.20
gatsby-plugin-intl: ^0.1.7 => 0.1.7
gatsby-plugin-manifest: ^2.1.1 => 2.1.1
gatsby-plugin-offline: ^2.1.1 => 2.1.1
gatsby-plugin-react-helmet: ^3.0.12 => 3.0.12
gatsby-plugin-remove-trailing-slashes: ^2.0.11 => 2.0.11
gatsby-plugin-sharp: ^2.1.2 => 2.1.2
gatsby-plugin-typography: ^2.2.13 => 2.2.13
gatsby-remark-copy-linked-files: ^2.0.13 => 2.0.13
gatsby-remark-images: ^3.0.14 => 3.0.14
gatsby-remark-prismjs: ^3.2.9 => 3.2.9
gatsby-remark-responsive-iframe: ^2.1.1 => 2.1.1
gatsby-remark-smartypants: ^2.0.9 => 2.0.9
gatsby-source-filesystem: ^2.0.37 => 2.0.37
gatsby-transformer-remark: ^2.3.12 => 2.3.12
gatsby-transformer-sharp: ^2.1.20 => 2.1.20
npmGlobalPackages:
gatsby-cli: 2.6.3
AdvThanksance!!!