vtellier/gatsby-plugin-intl-url

Issues with translated slugs

Opened this issue · 1 comments

I have this working great as standard and using the same URL's as my default language site. I'm now trying to implement the translates slugs using the JSON file.

When I add a test slug for the one page i'm testing this out on, my develop process shoots into an infinite loop and gives an output like the following.

Screenshot 2020-05-12 at 16 47 16

Any pointers for debugging this issue? Thanks

I'm getting similar issues, with Non-deterministic routing danger warnings.
I've noticed that placing this plugin resolver before gatsby-plugin-intl does make a difference, i.e.

{
	resolve: `gatsby-plugin-intl-url`,
	options: {
	defaultLanguage: defaultLanguage,
		translationFile: `./src/intl/slugs.json`
	}
},
{
	resolve: `gatsby-plugin-intl`,
	options: {
		path: `${__dirname}/src/intl`,
		languages: [
			'en',
			'sv'
		],
		defaultLanguage: 'en',
		redirect: false,
	},
},

I'd be interested in seeing what could be done to keep this project alive and making it work 😄 Is it still active?

This plugin seems to me like it is an important part of the gatsby-plugin-intl space. Not being able to translate slugs is somewhat problematic since it's a big SEO drawback. I'm currently using a onCreatePage "hack" in gatsby-node.js

The problem with this is:

  1. Max sub path depth is one (1)
  2. When changing language (with a rudimentary language switcher) the url isn't translated, i.e. the language changes just fine, however https://domain.com/about becomes https://domain.com/sv/about when it should be https://domain.com/sv/om (which does exist). A simple (but undesired) fix for this is to simply link the language switcher to the respective languages root, e.g. https://domain.com/sv/, https://domain.com/en/

OnCreatePage

const supportedLanguages = [
	'en',
	'sv'
];
const defaultLanguage = 'en';

const slugify = require('slugify');
const slugish = string => slugify(string, {
	replacement: '-',
	lower: true,
	locale: 'en',
});

/*==============================
 HANDLE PAGES ON CREATE
==============================*/
exports.onCreatePage = async ({
	page,
	actions: { createPage, deletePage },
}) => {
	supportedLanguages.forEach(language => {
		// DRY
		const pagePath = page.path;
		const languageRootPath = `/${language}/`;

		// Conditons for pages to handle
		if (
			pagePath.includes(language) &&
			language !== defaultLanguage &&
			pagePath !== '' &&
			pagePath !== languageRootPath &&
			pagePath !== `${languageRootPath}404/` &&
			pagePath !== `${languageRootPath}dev-404-page/`
		) {
			// Get translation
			const translation = require(`./src/intl/${language}.json`);
			const menuSlugs = translation.menu;
			const splitPath = pagePath.split('/');

			// Initiate empty slug
			let slug = '';

			// Loop path parts from split of page.path (const pagePath)
			splitPath.forEach((path, i) => {

				// First two (2) are "" and [LANGUAGE]
				if (path !== '' && path !== language) {

					// Skip zero (0) and one (1)
					if (i < 3) {

						// Match translated menu key with path and retreive slug
						slug = `${menuSlugs[path].slug}`;
					} else {

						// Make sure it is not 'undefined'
						if (typeof menuSlugs[splitPath[i - 1]] !== 'undefined') {

							// One (1) sublevel
							slug = `${slug}/${menuSlugs[splitPath[i - 1]][path].slug}`;
						} else {

							// Undefined, i.e. keep original path name
							slug = `${slug}/${path}`;
						}
					}
				}
			});

			// Prepend langauge code to slug
			slug = `/${language}/${slug}`;

			// create page for /[LANGUAGE]/[TRANSLATED_SLUG]
			const newPage = {
				...page,
				path: slug
			};

			// Create page with new slug and delete old page
			createPage(newPage);
			deletePage(page);
		}
	})
}

Language Switcher

import React from 'react';
import { IntlContextConsumer, changeLocale } from 'gatsby-plugin-intl';

const languageName = {
	en: "English",
	sv: "Svenska",
}

export default () => (
	<div>
		<IntlContextConsumer>
			{({ languages, language: currentLocale }) =>
				languages.map(language => (
					<a
						key={language}
						onClick={() => changeLocale(language)}
						style={{
							color: currentLocale === language ? `black` : `gray`,
							margin: 10,
							textDecoration: `underline`,
							cursor: `pointer`,
						}}
					>
						{languageName[language]}
					</a>
				))
			}
		</IntlContextConsumer>
	</div>
)