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 x-default in Multilanguage & Sitemap plugins #532

Merged
merged 3 commits into from
Feb 7, 2024

Conversation

ngdangtu-vn
Copy link
Contributor

@ngdangtu-vn ngdangtu-vn commented Dec 17, 2023

Description

Right now it is just a draft for discussion

Related Issues

Fix #528

Check List

  • Have you read the
    CODE OF CONDUCT
  • Have you read the document
    CONTRIBUTING
    • One pull request per feature. If you want to do more than one thing,
      send multiple pull request.
    • Write tests.
    • Run deno fmt to fix the code format before commit.
    • Document any change in the CHANGELOG.md.

@oscarotero
Copy link
Member

I wouldn't treat this option like another language code. I guess the use case of x-default is to provide a language selector to some pages (typically the homepage). This code should be in the head and in the sitemap (it affects also to the sitemap plugin).

I imagine a variable at page level to indicate that a page has a default lang. For example:

lang: en
langSelector: /country-selector/

Other option is mark one page as x-default. When the plugin detects this page, it's treated as a special page for selecting the language, and it's included as <link> in the other pages. My only question is if the link to the x-default page must be in all pages or only in the homepage.

lang: x-default

@ngdangtu-vn
Copy link
Contributor Author

My only question is if the link to the x-default page must be in all pages or only in the homepage.

Once users wish to support multiple languages with fallback system, x-default should be placed in all pages. Here is real life example:

homepage

content page

I guess the use case of x-default is to provide a language selector to some pages (typically the homepage)

You are correct, the main purpose of x-default is link to language selector page. Google said: "it was designed for language selector pages and so it will work best with those."1 However, Google didn't deny the fact that it could be used "the x-default value for any page"1. This can be understood as fallback pages can also be x-default value.

I wouldn't treat this option like another language code ... (it affects also to the sitemap plugin).

The reason I treat it as another language code (set 'x-default' in languages option) so that sitemap plugin can easily generate it. I belive it is the right idea because I check the sitemap plugin and found out that to generate language link list, it use alternates var from multilanguages plugin which will be easy if we inject x-default in to alternates var. On the other hand, x-default use the same value with normal hreflang. Isn't it is perfect reason to use it?

I imagine a variable at page level to indicate that a page has a default lang. For example:

lang: en
langSelector: /country-selector

You got a point. How about this:

  1. If plugin has config defaultLanguage and langSelector, then x-default value in each page is the langSelector page.
  2. If plugin has no config defaultLanguage and not langSelector, then we disable x-default feature.
  3. If plugin has config defaultLanguage and not langSelector, then x-default value in each page is the fallback page to the default language.
  4. If plugin has no config defaultLanguage but has langSelector, then x-default value in each page is the langSelector page.

With these cases, we can cover 2 usages (both recommend and side effect). x-default will be used as language selector page when langSelector involved (no 1, 4). x-default will be used as language fallback page when only defaultLanguage involved (no 3). Last one is a bit redundant when we disable x-default, because without defaultLanguage no bare index.html will be generated which users will likely choose one. But, well...

So with that thought, setting x-default as default option wasn't very good. I think I should only inject x-default after check all the cases carefully.

What do you think?

Footnotes

  1. https://developers.google.com/search/docs/specialty/international/localized-versions#xdefault 2

@oscarotero
Copy link
Member

The reason I think including x-default in the list of languages is a bad idea is because it's not really a language (there's no <html lang="x-default"> pages), it only specifies the relationship between two pages.

In this example (view-source:https://newtoninvestment.jp/) of a site in English and Japanese languages, the x-default page of the japanese language is the english version, even when english version is not the default language (English pages paths are prefixed with /en/).

What do you think about this?

  • The x-default page can be defined at page level with the defaultAlternate variable (name may change).
    • This allows to specify the language selector page globally for all pages, for example in a _data.yml file in the root of the project:
      defaultAlternate: /country-selector/
    • But also allows to customize the language selector for a specific page (overriding the variable in the front matter) or a group of pages (by creating a _data.yml file in a subfolder).
  • This variable could have a url (like /country-selector/) so it links to this url, or a language code (like defaultAlternate: en) to link to that language version.
  • By having the defaultAlternate variable at page level, the sitemap can also use it to generate the links.

@ngdangtu-vn
Copy link
Contributor Author

there's no pages

Yeah, my shortcut isn't worth for the sake of simplicity.

even when english version is not the default language

I don't think it is strange. They just tried to do fallback language for international visitors. Usually the best usage recommended by Google is for language selector page. But in both cases we saw, yours & mine are all used it as fallback language page rather than language selector page.

About your solution, I agree, but can we use the name langX because the x-default is clearly both selector and fallback (so 2 names we came up so far is not really match the purpose).

@oscarotero
Copy link
Member

About your solution, I agree, but can we use the name langX because the x-default is clearly both selector and fallback (so 2 names we came up so far is not really match the purpose).

Do you mean this?

lang: en
langX: /country-selector

Yeah, is shorter. The reason of suggesting defaultAlternate is because all alternate pages are stored in the alternates variable, so in the templates you have the alternates and defaultAlternate. But it's okay to use langX because alternates is a variable generated by Lume, not defined in the frontmatter.

In summary, it would work in this way:

  • The user can define the langX variable in the page or _data files.
  • The multilanguage plugin will read this variable to generate the alternateX variable.
    • If the variable is a URL (starts with /), the plugin searches the page with this url and creates the alternateX variable with the data of the page.
    • If the variable is a language code (like en) the alternateX is the data object of the page in alternates with the same language code.
    • If the variable is empty, the alternateX variable is empty.
  • The multilanguage plugin will add the x-default link using the alternateX value:
    if (page.data.alteranteX) {
      //insert <link rel="alternate" hreflang="x-default" href="...">
    }
  • The sitemap plugin will do the same.

What do you think?

@ngdangtu-vn ngdangtu-vn changed the title Support x-default in Multilanguage plugin Support x-default in Multilanguage & Sitemap plugins Dec 20, 2023
@ngdangtu-vn
Copy link
Contributor Author

ngdangtu-vn commented Dec 20, 2023

Sounds good, I'll work on the code now.

@ngdangtu-vn
Copy link
Contributor Author

ngdangtu-vn commented Dec 20, 2023

I didn't close this, it must be because I reset the branch to the latest. I'll reopen it with dummy commit for now :p

@ngdangtu-vn ngdangtu-vn reopened this Dec 20, 2023
@oscarotero oscarotero added this to the 2.1.0 milestone Dec 21, 2023
Copy link
Member

@oscarotero oscarotero left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! I just left a couple of comments.
I think the x-default should be handled after defining the alternates array, maybe in a different processor.

plugins/multilanguage.ts Outdated Show resolved Hide resolved
plugins/multilanguage.ts Outdated Show resolved Hide resolved
@ngdangtu-vn
Copy link
Contributor Author

  1. I'm concern about the UX. User could be easily mix up the defaultLanguage vs langX. Since both of them are about the fallback language. We should update and be clear in the documentation about this problem.
  2. Maybe the langX should also support http string (external link) for better scalability. (user can have a language gateway for multiple lume sites)

Thanks for the review, I'm working on it now.

@oscarotero
Copy link
Member

I'm thinking of maybe langX is not a good name. What you do think about noLang? to be clear that it's the url to follow when the user's language doesn't match with any available language in the site.

If we are going to allow external urls, maybe alternateX doesn't have to exist. Multilanguage plugin could just resolve the noLang value if its value is one of the available languages (like converting en to /en/...). And this url is all we need to build the alternate link and sitemap. We don't need the alternateX variable with the data object of the page.

@ngdangtu-vn
Copy link
Contributor Author

I'm thinking of maybe langX is not a good name

Upto now, I agree, it doesn't look good on user pov. But noLang could also be confused as well imho. I think about a longer name but more close to html standard: defaultHrefLang.

... maybe alternateX doesn't have to exist ... We don't need the alternateX variable with the data object of the page

I think so, in the best case, we don't have to expose a alternateX var. But I try to come up a case where developers really need a fully processed link. Maybe they need to display it in language switcher? If so should alternateX (which should have new name) be a string or a new type of object that can provide more information?

@oscarotero
Copy link
Member

But noLang could also be confused as well imho. I think about a longer name but more close to html standard: defaultHrefLang.

The problem of having "default" in the name is that it can be confused with the defaultLanguage option of the plugin. Maybe unknownLang? Or if we want a name more close to the x-default attribute, maybe xDefaultLang. If the variable only has the url of the page, I'd include the "url" somewhere: defaultLangUrl, unknownLangUrl, etc.

But I try to come up a case where developers really need a fully processed link. Maybe they need to display it in language switcher?

It would be possible. Let's say we use xDefaultLang variable:

<a href="{{ xDefaultLang }}">Language picker</a>

If you need to access to the page data:

{{ set xPage = search.page(`url=${xDefaultLang}`) }}

<a href="{{ xPage.url }}">{{ xPage.title }}</a>

Having only the URL in this variable, it's possible to use external URLs for the language picker. This can be useful for multidomain sites, where the language picker is, for example (example.com) and every language has its own domain (example.es, example.it) or subdomain (es.example.com, it.example.com, etc).

@ngdangtu-vn
Copy link
Contributor Author

having "default"... confused with the defaultLanguage option

That makes sense. It would confuses dev who try to get defaultLanguage variable.

... if we want a name more close to the x-default attribute, maybe xDefaultLang...

We still have default in the end, ain't it? I kinda want to avoid unknown word, it could be TypeScript keyword. The word itself wouldn't be very meaningful. The ideal word is fallback, but it could also be defaultLanguage. I ask ChatGPT for similar words:

image

image

I prefer standbyLangUrl and auxiliaryLangUrl or auxLangUrl. "Standby" sound more friendly to everyone and "auxiliary" make the sense out of x-default. What's about your opinion?

@oscarotero
Copy link
Member

Hmmm, naming thinks is complicated. 😄

We agree that the name should contain "lang" (obviously) and "url" (because it has a url, not a language code).
Fallback may make sense (fallbackLangUrl), but it looks like it's the url of the fallback language, which is not correct: there's no any fallback language because there's no language at all.

Maybe the most accurate name is unmatchedLangUrl: the url for when the user's language doesn't match with any of the site available language.

Does it make sense to you?

@ngdangtu-vn
Copy link
Contributor Author

unmatchedLangUrl

That sounds sexy. Let go with this :))

@ngdangtu-vn
Copy link
Contributor Author

Let me do one last confirm for this case. So now we will have:

  1. data.unmatchedLang is the input which can be lang-code, absolute path, external url
  2. data.unmatchedLangUrl is the output with proper URL that can be used

Is it ok to you, did I miss anything else?

@oscarotero
Copy link
Member

oscarotero commented Dec 25, 2023

I would use only one variable. It's like url variable: the user can define it as relative (./pathname/) and Lume resolves it.

unmatchedLang is fine (the url part can be omited, I think it's not confused now).

@ngdangtu-vn
Copy link
Contributor Author

ngdangtu-vn commented Dec 26, 2023

Now that I remember the url option also got rewritten from _data to layout/*. Ok, we can do the same thing with unmatchedLangUrl. But I don't think we should remove suffix "url". Like url is rewritten and *Url are also rewritten, that will make more sense right?

For now, I'll do with rewritable unmatchedLangUrl but still open for suggest any time you have new idea.

@oscarotero
Copy link
Member

Fair enough.
I suggested unmatchedLang because it's shorter, but unmatchedLangUrl is OK to me.

plugins/multilanguage.ts Outdated Show resolved Hide resolved
plugins/multilanguage.ts Outdated Show resolved Hide resolved
plugins/multilanguage.ts Outdated Show resolved Hide resolved
plugins/multilanguage.ts Outdated Show resolved Hide resolved
Features:
- support external links
- support internal absolute path
- support language code

Tasks:
- add feature
- improve message log
- update test cases
- update CHANGELOG
@oscarotero oscarotero merged commit b93dd0b into lumeland:main Feb 7, 2024
@oscarotero
Copy link
Member

Thanks for your great work!

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

Successfully merging this pull request may close these issues.

Multilanguage plugin: support x-default
2 participants