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

Support locale / language / i18n (e.g. /[lang]/about, /[lang]/features), when SvelteKit has a standard approach for locales #3

Closed
jasongitmail opened this issue Sep 16, 2023 · 12 comments

Comments

@jasongitmail
Copy link
Owner

jasongitmail commented Sep 16, 2023

Punting on this until SvelteKit natively supports i18n.

Will need to read a list of locales supported by the app (e.g. en, es), and a default locale (e.g. en) for which we will not add a URL segment (e.g. /features, /es/features).

Then need to look into hreflang elements:

<xhtml:link rel="alternate" hreflang="en" href="https://example.com/features"/>
<xhtml:link rel="alternate" hreflang="es" href="https://example.com/es/features"/>

Supporting info

Related SvelteKit issues to follow

  • i18n brainstorming - affects multiple aspects of potential sitemap support (e.g. where to find locales, are URLs translation--e.g. /hello and /hola instead of /hello and /es/hello, what to do if a translation is missing, etc)
  • translations
@jasongitmail jasongitmail changed the title Support for global params (e.g. [lang]) Support for globalParamValues (e.g. [lang]) Sep 16, 2023
@jasongitmail jasongitmail changed the title Support for globalParamValues (e.g. [lang]) Support for globalParamValues (e.g. /[lang]/about, /[lang]/pricing) Sep 16, 2023
@jasongitmail jasongitmail changed the title Support for globalParamValues (e.g. /[lang]/about, /[lang]/pricing) Support for globalParamValues (e.g. /[lang]/about, /[lang]/features) Sep 16, 2023
@jasongitmail jasongitmail changed the title Support for globalParamValues (e.g. /[lang]/about, /[lang]/features) Support local / language (e.g. /[lang]/about, /[lang]/features) Sep 17, 2023
@jasongitmail jasongitmail changed the title Support local / language (e.g. /[lang]/about, /[lang]/features) Support locale / language (e.g. /[lang]/about, /[lang]/features) Sep 17, 2023
@jasongitmail jasongitmail changed the title Support locale / language (e.g. /[lang]/about, /[lang]/features) Support locale / language (e.g. /[lang]/about, /[lang]/features), when SvelteKit has a standard approach for locales Oct 19, 2023
@jasongitmail jasongitmail changed the title Support locale / language (e.g. /[lang]/about, /[lang]/features), when SvelteKit has a standard approach for locales Support locale / language / i18n (e.g. /[lang]/about, /[lang]/features), when SvelteKit has a standard approach for locales Oct 24, 2023
@buhodev
Copy link

buhodev commented Dec 3, 2023

Hi, Jason! Thanks for the good work. Is there an update for this issue? I'm thinking of using this library for my website (after doing the sitemap manually 😅). Right now https://inlang.com/m/gerre34r/library-inlang-paraglideJs seems to be the goto solution for i18n in SvelteKit since the inlang team is collaborating with the sveltekit maintainers. What are your thoughts?

@jasongitmail
Copy link
Owner Author

jasongitmail commented Dec 3, 2023

What I could do create a solution that is independent of the i18n system being used. For example, a config property for Super Sitemap that lets the dev specify their default lang and an array of alternate langs.

  • PROs: It's not coupled to any particular i18n lib (yet).
  • CONs: Every route will be assumed to have a translation available (possibly a reasonable assumption).

Does that seem reasonable?

The Svelte maintainers help many devs, so I wouldn't consider Inlang to be the blessed SvelteKit i18n solution just yet. Imho, it's TBD what the best UX will be for an i18n solution in SvelteKit, given other cool solutions exist like https://lingui.dev/tutorials/cli, although not for SvelteKit yet. So I'd prefer to keep this agnostic to the i18n lib until there is an approach recommended by the SvelteKit docs or a defacto standard that is widely used.

@buhodev
Copy link

buhodev commented Dec 5, 2023

For example, a config property for Super Sitemap that lets the dev specify their default lang and an array of alternate langs.

Will this expose an option to work with the optional parameters feature that Super Sitemaps already supports? e.g.: having a [[lang]] route that accepts /de/* for German pages, and a default /* for English ones will generate the following sitemap for the home and about pages:

<urlset>
    <url>
        <loc>https://example.com/de</loc>
        <xhtml:link rel="alternate" hreflang="de" href="https://example.com/de" />
        <xhtml:link rel="alternate" hreflang="en" href="https://example.com/" />
    </url>
    <url>
        <loc>https://example.com/</loc>
        <xhtml:link rel="alternate" hreflang="de" href="https://example.com/de" />
        <xhtml:link rel="alternate" hreflang="en" href="https://example.com/" />
    </url>
    <url>
        <loc>https://example.com/de/about</loc>
        <xhtml:link rel="alternate" hreflang="de" href="https://example.com/de/about" />
        <xhtml:link rel="alternate" hreflang="en" href="https://example.com/about" />
    </url>
    <url>
        <loc>https://example.com/about</loc>
        <xhtml:link rel="alternate" hreflang="de" href="https://example.com/de/about" />
        <xhtml:link rel="alternate" hreflang="en" href="https://example.com/about" />
    </url>
</urlset>

instead of /en/* and /de/*:

<urlset>
    <url>
        <loc>https://example.com/de</loc>
        <xhtml:link rel="alternate" hreflang="de" href="https://example.com/de" />
        <xhtml:link rel="alternate" hreflang="en" href="https://example.com/en" />
    </url>
    <url>
        <loc>https://example.com/en</loc>
        <xhtml:link rel="alternate" hreflang="de" href="https://example.com/de" />
        <xhtml:link rel="alternate" hreflang="en" href="https://example.com/en" />
    </url>
    <url>
        <loc>https://example.com/de/about</loc>
        <xhtml:link rel="alternate" hreflang="de" href="https://example.com/de/about" />
        <xhtml:link rel="alternate" hreflang="en" href="https://example.com/en/about" />
    </url>
    <url>
        <loc>https://example.com/en/about</loc>
        <xhtml:link rel="alternate" hreflang="de" href="https://example.com/de/about" />
        <xhtml:link rel="alternate" hreflang="en" href="https://example.com/en/about" />
    </url>
</urlset>

Does that seem reasonable?

Sure! Is it feasible to have a special exclude property for routes that don't have a translation available yet? Or add those cases to the excludePatterns property? That way we don't have CONs

@jasongitmail
Copy link
Owner Author

jasongitmail commented Dec 5, 2023

Or add those cases to the excludePatterns property?

Yep, the existing excludePatterns could be made to cover this, I'm confident, so it would be possible to exclude any particular route (e.g. /de/about) or route pattern (e.g. /de/campsites/*) as needed.

Will this expose an option to work with the optional parameters feature that Super Sitemaps already supports? e.g.: having a [[lang]] route that accepts /de/* for German pages, and a default /* for English ones will generate the following sitemap for the home and about pages:

I think we have the same end goal in mind, where the default language exists at the shorter path (e.g. /about for English or whatever is preferred) and alternate languages are part of the path (e.g. /de/about).
__

Question: On your site, do all of your routes exist within a directory that is an optional parameter, like [[lang]]?

@buhodev
Copy link

buhodev commented Dec 5, 2023

Question: On your site, do all of your routes exist within a directory that is an optional parameter, like [[lang]]?

Yes and no. All content routes do exist within a [[lang]], but I have a api/* route as well (I don't want this to appear in the sitemap tho, because they're server routes). The structure is something like this:

  • [[lang]]/
    • +page.svelte
    • about/
      • +page.svelte
  • api/
    • search/
      • +server.ts

P.S: This could already work (partially) for my use case but I'm still generating the sitemap manually because I need the alternate links.

@jasongitmail
Copy link
Owner Author

jasongitmail commented Dec 5, 2023

Okay. Thanks. I'm going to think on this a bit more, but have an idea how to approach it now. I can't get to this immediately, but probably later this month.

(I don't want this to appear in the sitemap tho, because they're server routes)

No worries there. Super Sitemap only includes routes containing a *.svelte file for this reason.

@jasongitmail
Copy link
Owner Author

@buhodev i18n support is now included in v0.14.12 on NPM.

Instructions are available in the README. Let me know if anything is unclear please.

I misspoke earlier about excludePatterns working to also exclude specific specific language path (e.g. /es/about). The existing excludePatterns will not work for that, b/c it checks routes to exclude. But the goal you described, would exclude a specific version of a given route, meaning it needs to run after paths are created, using any paramValues to replace parameters.

I need to give it more thought--how to expose it in the config and docs for the best DX, etc. But wanted to get this out and available.

@jasongitmail
Copy link
Owner Author

@buhodev let me know if you get a chance to test this on your site, so I can be sure it's working for others too.

I'm closing this thread as completed, and created a new issue for adding excludePathPatterns.

@buhodev
Copy link

buhodev commented Dec 20, 2023

Hi, @jasongitmail! Sorry for the late response (I forgot to check this issue earlier) and thanks for the new feature!

From a quick test, I'm facing an issue right now with the way I'm defining my dynamic route with matching.

I'm following the example from the docs:

import * as sitemap from 'super-sitemap';
import type { RequestHandler } from '@sveltejs/kit';

export const prerender = true; // optional

export const GET: RequestHandler = async () => {
	return await sitemap.response({
		origin: 'https://syself.com',
		lang: {
			default: 'en', // e.g. /about
			alternates: ['de'] // e.g. /zh/about, /de/about
		},
		paramValues: {
			// '/[[lang=lang]]': ['', 'de']
		}
	});
};

And I'm getting this error:

Error: Sitemap: paramValues not provided for: '/[[lang=lang]]'
Update your sitemap's excludedPatterns to exclude this route OR add data for this route's param(s) to the paramValues object of your sitemap config.

In the docs I saw that this dynamic route must be name [[lang]], but I'm using [[lang=lang]]. From a quick read to the implementation code this is not possible, right? Or I'm doing something wrong with the config?

If I uncomment this line:

import * as sitemap from 'super-sitemap';
import type { RequestHandler } from '@sveltejs/kit';

export const prerender = true; // optional

export const GET: RequestHandler = async () => {
	return await sitemap.response({
		origin: 'https://syself.com',
		lang: {
			default: 'en', // e.g. /about
			alternates: ['de'] // e.g. /zh/about, /de/about
		},
		paramValues: {
+			'/[[lang=lang]]': ['', 'de']
		}
	});
};

I get this error:

Error: Sitemap: paramValues not provided for: '/[[lang=lang]]/about'
Update your sitemap's excludedPatterns to exclude this route OR add data for this route's param(s) to the paramValues object of your sitemap config.

@jasongitmail
Copy link
Owner Author

jasongitmail commented Dec 20, 2023

  • Ah, my implementation expects [[lang]] exactly, without any param matchers. I suppose param matchers are good to support too; I'll open an issue.
  • In the meantime, just change your directory name to use [[lang]] instead of [[lang=lang]]. Also, omit the paramValues if it's only the language; the lang does not need to be provided within the paramValues' data values, it just needs to be part of each paramValue key when specifying paramValues is required (e.g. [[lang]]/blog/[post]: ['hello-world', 'another-post'])
  • Note: This 2nd aspect is one part I'm not settled on how to best simplify yet. One idea I had is to instruct devs to not include [[lang]] as part of their key for any paramValues, but that could be unintuitive when the dev has some routes within a [[lang]] dir and some not within such a dir; and the implementation within super sitemap would need to be totally refactored. It still might be a preferable solution. LMK your opinion too.

@buhodev
Copy link

buhodev commented Dec 20, 2023

It worked flawlessly 😄 Thanks!

This 2nd aspect is one part I'm not settled on how to best simplify yet

I see the problem. Right now I can't imagine what routes could go outside of the [[lang]] folder for them not to be included in the i18n but on the sitemap. I guess api routes (that go outside [[lang]]) don't need to be localized, but they are not included in the sitemap either.

Another corner case would be /[[another-dynamic-param]] in the root alongside [[lang]] (if that's even possible). Then it might be good idea to prepend routes with [[lang]]/ in the paramValues.

Maybe an idea:

return await sitemap.response({
	paramValues: {
		// 'lang_only' (super-sitemap prepends [[lang]] automatically)
		// 'no_lang' (user needs to prepend any dynamic path in the keys)
		// ...more options
		$mode: 'lang_only',
		'/blog/[post]': ['hello-world', 'another-post'],
	}
});

@jasongitmail
Copy link
Owner Author

It worked flawlessly 😄 Thanks!

Awesome 😄

hmm That's a new idea. I'll think on it a bit. Generally, I'm averse to adding options and prefer opinionated approach that simplifies/reduces what new devs are required to learn, to make it easiest to use.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants