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

Feature request: i18n #23

Open
aligajani opened this issue Oct 31, 2018 · 22 comments

Comments

@aligajani
Copy link

commented Oct 31, 2018

No description provided.

@hjvedvik

This comment has been minimized.

Copy link
Member

commented Nov 11, 2018

We haven't looked much into how i18n should work in Gridsome yet, but we are open for discussion if anyone has a good idea :)

@TomPichaud

This comment has been minimized.

Copy link

commented Dec 21, 2018

Hugo is doing it really well, maybe also have a look at JSLingui, v3 is promising. A lot of users are waiting for an easy/fully working way to do it with Gatsby... will you be the first ?

@cypris75

This comment has been minimized.

Copy link

commented Feb 2, 2019

I think this is a must-have nowadays. Would definitely consider Gridsome if i18n would be available.

@hjvedvik hjvedvik pinned this issue Feb 6, 2019

@hjvedvik hjvedvik unpinned this issue Feb 6, 2019

@gunta

This comment has been minimized.

Copy link

commented Feb 15, 2019

This blog nails it
https://blog.davidpaternina.com/choosing-a-static-site-generator/

Having used Vuepress myself, I didn't had any major complaint with it, so I think its good enough as a starting point
https://vuepress.vuejs.org/guide/i18n.html

@arttemiuss43

This comment has been minimized.

Copy link

commented Feb 16, 2019

I think we can use different domains (or subdomains) for internationalization. If the website is deployed by netlify we can use netlify build variables to determine what language key to use for specific domain. Something like APP_LANG=de.

@cypris75

This comment has been minimized.

Copy link

commented Feb 16, 2019

I am using Vuepress now and I like the way they handle it:

  • Subfolder for each new language
  • Language code is part of the front-matter so href lang tag is used correctly
  • Frontmatter defines title and meta information for each language
  • Sidebar and Navigation bar can be configured for each language

Downside (from a SEO perspective):

  • slug is the same for each language but look at the article mentioned by @gunta There seems to be a solution.
@gevera

This comment has been minimized.

Copy link

commented Feb 20, 2019

The only thing that stops me from using Gridsome right now is internationalization. I know guys from Nuxt have their own i18n implementation. I'll leave a link for future references. https://nuxt-community.github.io/nuxt-i18n/

@tomtev

This comment has been minimized.

Copy link
Member

commented Feb 20, 2019

@oliverdozsa

This comment has been minimized.

Copy link

commented Mar 2, 2019

What about vue-i18n?

@Vlasterx

This comment has been minimized.

Copy link

commented Mar 9, 2019

Here is my suggestion on how to solve i18n problem with Gridsome:

Organizing static content

This is how markdown settings look in gridsome.config.js:

plugins: [
  {
    use: '@gridsome/source-filesystem',
    options: {
      path: 'src/articles/blog/**/*.md',
      typeName: 'BlogPost',
      route: '/blog/:slug'
    }
  }
]

We don't need to add any new functionality to change our organizational structure for multilingual content. Lets say that we want to add 2 markdown sources for 2 languages, where English is set as default, while Serbian is set as secondary language. Source for content can be kept is separate folders:

  • English source folder src/articles/blog/en/
  • Serbian source folder src/articles/blog/sr/

Settings can look like this:

plugins: [
  {
    use: '@gridsome/source-filesystem',
    options: {
      path: 'src/articles/blog/en/**/*.md', // Added `en` in source path
      typeName: 'BlogPostEn', // Added `En` at the end of the value
      route: '/blog/:slug' // Nothing is added to route if we want to keep it as default
    }
  },
  {
    use: '@gridsome/source-filesystem',
    options: {
      path: 'src/articles/blog/sr/**/*.md', // Added `sr` in source path
      typeName: 'BlogPostSr',  // Added `Sr` at the end of the value
      route: '/sr/blog/:slug'  // Added `sr` to URL route, since everything related to this language should be in routes that start with `/sr/` 
    }
  }
]

We can organize our pages in the similar manner. In our src/pages/ folder, everything we keep in root folder can be used for default language, while translated pages can be moved to folders with language names.

Root folder for pages is /src/pages/ and inside of it we can have structure like this one

About.vue
Index.vue
/sr/Opsirnije.vue      <-- translated `About.vue`
/sr/Index.vue          <-- Translated `Index.vue` 

What we lack in both cases is option to connect these languages logically. For this to work, we will need to have some kind of language router file where we can connect translated content.

Lets say that routing can be handled as simple as this:

[ // Array of all paths
  {
    en: "/",                // `src/pages/Index.vue
    sr: "/sr/"              // `src/pages/sr/Index.vue
  }, 
  {
    en: "/about/",          // `src/pages/About.vue`
    sr: "/sr/opsirnije/"    // `src/pages/sr/Opsirnije.vue`
  },
  {
    en: "/blog/",           // `src/articles/blog/en/**/*.md`
    sr: "/sr/blog/"         // `src/articles/blog/sr/**/*.md`
  }
]

This can be useful for language switcher component that would need to be developed.

This routing would handle basic routes, we can even add routes for specific blog articles in here without any advanced logic behind it, but for the larger sites this may prove to be cumbersome.

[
  // ... Other routes...
  {
    en: "/blog/blog-article-1",
    sr: "/sr/blog/blog-clanak-1"
  }
]

Important thing to remember is that some sites will be deliberately missing some of the content for some languages. Lets say that we have third language here... Spanish, and that for Spanish we don't want to have blogging component. In that case we would leave out that route from this file.

When Language Switcher component is developed, selecting different language should switch route for route that was set in this file. If the route is not set, best option would be to change it to index page / root URL for that language.

Pluralization

In some cases we want to develop components that are not translated as a whole, like articles or blog posts, but only have strings that need to be translated. In this case we would need to have files with string translations. Lets say that we would keep them in /src/localization/ separated by folders with short language names en, sr, es...

Pluralization rules: http://docs.translatehouse.org/projects/localization-guide/en/latest/l10n/pluralforms.html?id=l10n/pluralforms

Another explanation for pluralization rules: http://i18njs.com/#pluralisation

Lets say that you want to create a component that counts the number of articles. English translation for the number of articles could be:

  • There is 1 article
  • There are 5 articles

Serbian translation would be different:

  • Postoji 1 članak
  • Postoji 3 članka
  • Postoji 12 članaka

Each language file can created to be something like this:

/src/localization/en.js

export default {
  en: {
    dateFormat: "YYYY-MM-DD",
    plural: "nplurals=2; plural=(n != 1);",
    strings: {
      "_ARTICLE_1": [
        "There is",
        "There are"
      ],
      "_ARTICLE_2": [
        "article",
        "articles"
      ]
    }
  }
}

Serbian should look like this

/src/localization/sr.js

export default {
  sr: {
    dateFormat: "DD. MM. YYYY.",
    plural: "nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);",
    strings: {
      "_ARTICLE_1": [
        "Postoji",
        "Postoji", // Same for all situations
        "Postoji",
      ],
      "_ARTICLE_2": [
        "članak",
        "članka",
        "članaka"
      ]
    }
  }
}

Ideally, this is how would translateable strings look in our component:

<template>
  <p>{{ t('_ARTICLE_1', this.articleCount) this.articleCount t('_ARTICLE_1', this.articleCount) }}</p>
</template>

<script>
export default {
  data(): {
    return {
      language: "en",
      articleCount: 2
    }
  }
}
</script>

Result for English would be

<p>There are 2 articles</p>

Result for Serbian would be

<p>Postoji 2 članka</p>

Translation function t(string, no) should take 2 parameters

  • string - string identifier that returns translation based on pluralization rules
  • no - optional number used for pluralization. Based on plural rule defined in language file, it will select the correct string to display. If this number is omitted, then only the first translated string should be used in output. t('_ARTICLE_1') for en would return "There is".

Setting proper HTML tags

We can use htmlAttrs to set page language.

<script>
export default {
  data(): {
    return {
      language: "en",
      articleCount: 2
    }
  },
  metaInfo() {
    return {
      htmlAttrs: {
        lang: this.language
      }
    }
  }
}
</script>

I hope that these ideas may help with further development.

@robaxelsen robaxelsen added the question label Mar 11, 2019

@robaxelsen robaxelsen changed the title i18n? Feature request: i18n Mar 11, 2019

@gevera

This comment has been minimized.

Copy link

commented May 12, 2019

Will i18n support be on the official roadmap?

@tomtev tomtev added this to To prioritize in Gridsome Roadmap via automation May 20, 2019

@OfekA

This comment has been minimized.

Copy link

commented Jun 11, 2019

This is the only requirement for us in order to migrate from Nuxt, which we would love to do, any updates on progress?

@xyNNN

This comment has been minimized.

Copy link

commented Jul 11, 2019

What's about this feature? Is there any plans about the i18n feature for Gridsome?

@chug2k

This comment has been minimized.

Copy link

commented Jul 28, 2019

Sorry to spam, but been watching for a long time and would really like to get this on the roadmap (and I think a lot of others do too)

@simduchaine

This comment has been minimized.

Copy link

commented Jul 30, 2019

Really need this indeed! (and fast)

@Epenance

This comment has been minimized.

Copy link

commented Aug 7, 2019

This feature would indeed be great, or at least a guide line to how you would implement a multi language site.

Considering moving my personal site, a custom Angular app with WordPress over to Gridsome with Markdown files, but I need multi language in order to get this to work.

@jxlstudio

This comment has been minimized.

Copy link

commented Aug 7, 2019

Can't be "Ready for global domination" without internationalization built in.

@aligajani

This comment has been minimized.

Copy link
Author

commented Aug 10, 2019

@sustained

This comment has been minimized.

Copy link

commented Aug 11, 2019

👍 for i18n support.

Nuxt has official i18n support, perhaps look at how they're doing it. I was pretty happy with how it works there.

@chug2k

This comment has been minimized.

Copy link

commented Aug 21, 2019

@tomtev / @hjvedvik any updates here? 😇

@Maxhodges

This comment has been minimized.

Copy link

commented Aug 22, 2019

@tomtev @hjvedvik i18n has 5-10x more votes than other issues in both the "to prioritize" lists and also in the "prioritized" lists. Seems like it should get more attention, no?

i'd pay to make it a priority. We'd love to use Gridsome but we are building everything with Vuepress because we make multi-lingual sites: example

@hjvedvik

This comment has been minimized.

Copy link
Member

commented Aug 22, 2019

@chug2k @Maxhodges I know some people are creating i18n sites with Gridsome using the Pages API, but there is no built-in solution that works for all sources automatically yet, unfortunately. This issue is something we are working towards by making the required changes in core first. We are not quite ready to implement it yet but are getting much closer with the 0.7 release :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.