Skip to content

Only generate the site for the language set in DEFAULT_LOCALE #134

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

Open
Zyles opened this issue Feb 24, 2025 · 16 comments
Open

Only generate the site for the language set in DEFAULT_LOCALE #134

Zyles opened this issue Feb 24, 2025 · 16 comments

Comments

@Zyles
Copy link

Zyles commented Feb 24, 2025

Describe the bug

I am using no_prefix strategy with DEFAULT_LOCALE to generate a two language site into static.

Each site has its own TLD specific domain and static repository. So they are completely separated by only changing the translation.

The problem is when running nuxi generate it will create all the pages for both languages, which will be wrong since index will only be in the one language, but with translated subpages.

This will create SEO problems since that will create duplicated content across two sites. Also since using the sitemap plugin with nuxt it will be crawled by search engines even if the links are not active on the generated site.

I think the correct behaviour when using no_prefix strategy in combination with DEFAULT_LOCALE it should only generate the site with the language set in locale, not any translated pages. Or at least have the option to use this behaviour.

@s00d
Copy link
Owner

s00d commented Feb 24, 2025

I don't really understand the issue. no_prefix physically can't create all the pages for both languages. When no_prefix is used, there is no modification of the routes at all, and the routing logic is taken from Nuxt. The locale is passed simply via the defaultLocale parameter (I hope you're changing defaultLocale before running generate?). Please provide a simple example—maybe then I'll be able to understand it better.

@Zyles
Copy link
Author

Zyles commented Feb 26, 2025

I researched some more.

When having $defineI18nRoute on contact.vue:

$defineI18nRoute({
  localeRoutes: {
    en: "/contact",
    se: "/kontakt",
  },
});

It will generate the other language page even if DEFAULT_LOCALE is set.

@s00d
Copy link
Owner

s00d commented Feb 26, 2025

I researched some more.

When having $defineI18nRoute on contact.vue:

$defineI18nRoute({
  localeRoutes: {
    en: "/contact",
    se: "/kontakt",
  },
});

It will generate the other language page even if DEFAULT_LOCALE is set.

So this is completely expected behavior. How else do you imagine switching the language in no_prefix mode? The router needs to know all the links that can be navigated to, even if a different locale is set. The module generates all possible links, and the router manages navigating to the required page.

@Zyles
Copy link
Author

Zyles commented Mar 1, 2025

I researched some more.
When having $defineI18nRoute on contact.vue:

$defineI18nRoute({
  localeRoutes: {
    en: "/contact",
    se: "/kontakt",
  },
});

It will generate the other language page even if DEFAULT_LOCALE is set.

So this is completely expected behavior. How else do you imagine switching the language in no_prefix mode? The router needs to know all the links that can be navigated to, even if a different locale is set. The module generates all possible links, and the router manages navigating to the required page.

By creating two different .output/public statically generated websites. It is two different websites on their own domains translated per domain. I'm not swapping the translation on the fly and not running a node instance since the website is statically generated.

The language switcher is an actual "domain switcher" which points to another TLD.

So changing the DEFAULT_LOCALE would create the correct language on index and the translated links + pages.

Otherwise I would need to have two different repos (+1 for each language) for the same website, or all websites would have the same content accessable by sitemap.

@s00d
Copy link
Owner

s00d commented Mar 1, 2025

In version v1.77.0, a new parameter called noPrefixRedirect was added link. If you enable it, it will set up a redirect instead of the standard routes. Please give it a try. In the future, be sure to describe your problem in detail and provide an example.

@Zyles
Copy link
Author

Zyles commented Mar 4, 2025

In version v1.77.0, a new parameter called noPrefixRedirect was added link. If you enable it, it will set up a redirect instead of the standard routes. Please give it a try. In the future, be sure to describe your problem in detail and provide an example.

Well I did. I didn't know what was causing it.

But this change redirects it to 404 and instead redirects it to the other language. It should be reversed to redirect it to the generated language.

Maybe another solution would be to filter out all routes in $defineI18nRoute that do not match the locale before crawling?

@s00d
Copy link
Owner

s00d commented Mar 12, 2025

Provide an example project with reproduction steps.

@Zyles
Copy link
Author

Zyles commented Mar 12, 2025

Here:
https://github.com/Zyles/nuxt-i18n-micro/tree/no-prefix-redirect-test

I have a suspicion there is a problem with paths on the disk. I am running Git bash on Windows. If you are not getting these problems I assume you are on another OS.

$ npm run generate:en && ls .output/public/
200.html  _locales/  _payload.json  dir1/       locales/    page/    seite/      subpage/
404.html  _nuxt/     contact/       index.html  no_prefix/  pageEN/  stranitsa/  unlocalized/
$ npm run generate:de && ls .output/public/
200.html  404.html  _locales/  _nuxt/  _payload.json  contact/  index.html  locales/  seite/  stranitsa/

Notice "contact/" directory which is incorrect. Should be "kontakt/"

I think this line might be a problem, but I have been unable to find the issue:

const normalized = path.posix.normalize(routePath).replace(/\/+$/, '')

or this:
const fullPath = path.posix.normalize(`${parentPath}/${page.path}`) // Объединяем путь родителя и текущий путь

Because isCustom is false in:

isCustom: boolean,

When I:

private createLocalizedRoute(
    page: NuxtPage,
    localeCodes: string[],
    originalChildren: NuxtPage[],
    isCustom: boolean,
    customPath: string = '',
    customRegex?: string | RegExp,
    force = false,
  ): NuxtPage | null {

  console.log('page: ', page, 'localeCodes: ', localeCodes, 'originalChildren: ', originalChildren, 'isCustom: ', isCustom, 'customPath: ', customPath, 'customRegex: ', customRegex, 'force: ', force)
Output:
page:  { name: 'contact',
  path: '/contact',
  file:
   '<path>/pages/contact.vue',
  children: [] } localeCodes:  [ 'en', 'ru', 'fr', 'ch' ] originalChildren:  [] isCustom:  false customPath:   customRegex:  undefined force:  false

Please confirm correct output.

Can you advice on how to install nuxt sitemap for testing in the playground? I get the error:

$ cd playground && npx nuxi@latest module add sitemap
[ nuxi ]  WARN  No nuxt dependency detected in <path>/playground
 ERROR  TTY initialization failed: uv_tty_init returned EBADF (bad file descriptor)

@s00d
Copy link
Owner

s00d commented Mar 12, 2025

Now I understand the issue; it was indeed related to the OS. I fixed it in version 1.79.0.

Please try updating.

Can you advice on how to install nuxt sitemap for testing in the playground? I get the error:

$ cd playground && npx nuxi@latest module add sitemap
[ nuxi ]  WARN  No nuxt dependency detected in <path>/playground
 ERROR  TTY initialization failed: uv_tty_init returned EBADF (bad file descriptor)

Try installing it manually:

npm i @nuxtjs/sitemap

Or add it to your package.json:

"devDependencies": {
  "@nuxtjs/sitemap": "^7.2.5"
}

Then, include it in nuxt.config.ts:

export default defineNuxtConfig({
  modules: [
    //...
    '@nuxtjs/sitemap',
  ],
})

If this doesn’t help, it's best to reach out to the developers of @nuxtjs/sitemap.

@Zyles
Copy link
Author

Zyles commented Mar 13, 2025

Thanks, now this URL works, but I found another bug.

The translation is redirecting to the defaultLocale, so it will always be english.

See the updated repo branch and changes:
Zyles@0f54f69

$ npm run generate:de && npx serve .output/public/

If you refresh page you can see it reverting the translation.

Another issue, this part in index.vue:

$defineI18nRoute({
  locales: {
    en: {
      navigation: {
        contact: 'Contect en',
      },
    },
    de: {
      navigation: {
        contact: 'Contect de',
      },
    },
    ru: {},
    fr: {},
    ch: {},
  },
})

Always overrides the entire object "navigation", it does not merge the keys. Maybe this is intended? But if you add in your locales/en.json with navigation.title for example it is never found if you have this $defineI18nRoute defined.

Oh and also localeRoute({ name: 'contact' }) does not update the link path in dynamic mode when running "npm run dev". Only when static generating.

@s00d
Copy link
Owner

s00d commented Mar 13, 2025

The translation is redirecting to the defaultLocale, so it will always be english.

The translation won't be in English if you're visiting the site for the first time. On subsequent visits, the translation will be determined by the no-prefix-locale.

For example, if you started in dev mode, changed the language, then switched to production and visited the site, it would use the locale from no-prefix-locale. The same applies if you started in production, changed the language, restarted, and visited again.

This behavior is intentional to preserve the user's locale, and it should work this way in production mode.

Always overrides the entire object "navigation", it does not merge the keys. Maybe this is intended? But if you add in your locales/en.json with navigation.title for example it is never found if you have this $defineI18nRoute defined.

Unfortunately, there's nothing I can do here—that's the intended behavior. The complex logic for merging objects requires a lot of resources and can cause significant issues. Simply avoid using duplicate paths; navigation_component.contact will resolve your issue.

Oh and also localeRoute({ name: 'contact' }) does not update the link path in dynamic mode when running "npm run dev". Only when static generating.

Your links are only generated when the page loads—Vue doesn’t track changes after that. You need to do something like this:

<template>
  <h1>{{ $t('navigation.title') }}</h1>
  <ul class="space-y-0 rounded-xl p-4">
    <li
      v-for="(link, index) in navLinks"
      :key="index"
    >
      <NuxtLink :to="localeRoute({ name: link.to })">
        <span>
          {{ link.label }}
        </span>
      </NuxtLink>
    </li>
  </ul>
</template>

<script setup lang="ts">
const { localeRoute, $t } = useI18n()

const navLinks = computed(() => [
  {
    to: 'index',
    label: $t('navigation.home'),
  },
  {
    to: 'contact',
    label: $t('navigation_component.contact'),
  },
])
</script>

<style scoped>
</style>

By wrapping navLinks in computed(), it will dynamically update when the locale changes.

@Zyles
Copy link
Author

Zyles commented Mar 13, 2025

Something is still bugged. I am using incognito mode so it should be fresh for every visit. I even closed down the browser.

I updated the branch: https://github.com/Zyles/nuxt-i18n-micro/tree/no-prefix-redirect-bug

$ npm run generate:de && npx serve .output/public/

Correct:
Image

Url: /kontakt:

Image

New incognito browser:

$ npm run generate:en && npx serve .output/public/

Image

Incorrect:

Url: /kontakt, should be /contact/:
Image

Also noted in sitemap.xml it generates urls for both languages when using EN (defaultLocale, fallbackLocale):

    <url>
        <loc>https://example.com/contact</loc>
    </url>
    <url>
        <loc>https://example.com/kontakt</loc>
    </url>

Which would be incorrect too.

@Zyles
Copy link
Author

Zyles commented Apr 14, 2025

Were you able to reproduce my last issue?

@s00d
Copy link
Owner

s00d commented Apr 15, 2025

Yes, but I don't have time to fix this now — it's complicated and I’m not sure how to fix it.

@s00d
Copy link
Owner

s00d commented Apr 15, 2025

I looked at it again and think I’ve found the main issue. Try version v1.83.2. There are still some problems; for example, a route can be opened by two links if it’s added through localeRoutes. I’ll keep working on it.

@s00d
Copy link
Owner

s00d commented Apr 15, 2025

added redirect logic in v1.83.3

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

No branches or pull requests

2 participants