untra / polyglot

:abc: Multilingual and i18n support tool for Jekyll Blogs
https://polyglot.untra.io
MIT License
417 stars 60 forks source link

Collections #188

Closed ctsstc closed 8 months ago

ctsstc commented 9 months ago

Documentation

Jekyll

I'm following the documentation for how collections are handled here:

Polyglot

There does not seem to be any documentation around how to handle collections in Polyglot.

Research

I did find these issues:

Configuration

I've included lang in the front matter, but the given page continues to render English/default for the included collection.

We do have have the output: true for those collections so they do end up in the build of the site, but as for including them as described in the Jekyll documentation, does not seem to work unfortunately.

We're also utilizing the manual ordering which points to a direct document:

?¿

I'm wondering what the best way to go about this is?

Some Thoughts...

Expectations

There's a couple of interesting issues that collections bring up that I would expect them to behave a certain way.

Build Outputting

You can apply a layout to collections so that those pages are output against a template during build time. Currently if you have something like _collections/_posts/some-post.md and _collections/_posts/some-post-zh.md it will build that out, but we end up with some oddities because we'll have all of these files:

I would expect there to only be the following:

Includes Outputting

https://jekyllrb.com/docs/collections/#output

I would expect it to pull the associated language when utilizing the globals, or to have some escape hatch to access them.

{% for staff_member in site.staff_members %}
  <h2>{{ staff_member.name }} - {{ staff_member.position }}</h2>
  <p>{{ staff_member.content | markdownify }}</p>
{% endfor %}

My current hacky method is something like this:

{% assign filtered-portfolio = site.portfolio | where_exp:"item","item.profile-status != 'hidden' and item.lang == 'en'" %}

{% for item in filtered-portfolio %}
  {% include portfolio-card.html %}
{% endfor %}

I also then need to add the other language file to the configuration for sorting purposes as well under: _config.yml collections.portfolio.order.

george-gca commented 8 months ago

I was able to implement this. Take a look at my template site, where I have the projects collection.

ctsstc commented 8 months ago

@george-gca was there anything special you had to do to get this to work?

I was checking out the config and the localization-exists plugin (I imagine that's not required though? but wasn't sure what that's doing).

Thanks for posting your template site, it seems to be quite feature loaded 💯 🙏

george-gca commented 8 months ago

I just realized that in my template the projects are correctly translated, but when I try to change languages inside one of them it fails. I will fix this and come back to explain it more thoroughly.

ctsstc commented 8 months ago

I noticed you are running the Jekyll serve it seems for the docker container. I was was interested if that's just for development purposes? I was able to grab all the dependencies on my Mac and get your site to build out.

It does seem that your pt-br projects directory builds out like: /pt-br/projects/pt-br/ which is likely an issue.

The other part that kind of felt odd to me was seeing /projects/en-us/ Shouldn't it drop the en-us since it's the default language?

image
george-gca commented 8 months ago

Ok I just fixed it. And yes, docker here is for development purposes. It is easier to ensure you have the right versions of the libraries and everything with a docker image.

I have in my template 2 custom collections: news and projects, as you can see here.

To make it work, what I did was:

  1. Add the collections to _config.yml. Note that the permalink here is important. I added it as:
    collections:
    news:
    defaults:
      layout: post
    output: true
    permalink: /:collection/:title/
    projects:
    output: true
    permalink: /:collection/:title/
  2. Create the collections, for example, projects, with one subdir per language. In my case, for the project 1 page, I needed to create _projects/en-us/1_project.md and _projects/pt-br/1_project.md. In both files' frontmatter I added:
    ---
    page_id: project_1
    ---
  3. Note that I didn't use any language in the frontmatter. The language is going to be defined by its path, since I added lang_from_path: true to my _config.yml from polyglot configuration. The code will know which file to select for the translation based on the page_id variable here.
ctsstc commented 8 months ago

Thanks for all the help on this. I'm finding this commit quite useful as well: https://github.com/george-gca/multi-language-al-folio/commit/5bb365a845a5165df27b93c9a69cd28236c2300e

This is also helping answer a question that I've had that didn't seem to be documented for Polyglot either which is having a centralized i18n file like I'm used to with so many other languages/libraries, so that I don't have to duplicate templates everywhere for each language which would result in a ton of duplication and a pain maintaining/changing later on ie: _data/en-us/strings.yml.

I'm rather new to Jekyll so seeing stuff like: https://github.com/george-gca/multi-language-al-folio/commit/c1f168473f7cddb32c24404607e4fd181d189132 or the how you handled plugins to give additional functionality to liquid is super helpful as well thank you ^__^

This definitely look much better! 🎉

image
george-gca commented 8 months ago

Thanks for all the help on this. I'm finding this commit quite useful as well: https://github.com/george-gca/multi-language-al-folio/commit/5bb365a845a5165df27b93c9a69cd28236c2300e

This was the commit where I fixed the issue lol.

This is also helping answer a question that I've had that didn't seem to be documented for Polyglot either which is having a centralized i18n file like I'm used to with so many other languages/libraries, so that I don't have to duplicate templates everywhere for each language which would result in a ton of duplication and a pain maintaining/changing later on ie: _data/en-us/strings.yml.

I recently answered questions about this here and here. This was how I used to do with the previous multi language plugin that was discontinued. I decided to still do it like this in some places, while in other places it makes more sense to use the translated string directly.

I'm rather new to Jekyll so seeing stuff like: https://github.com/george-gca/multi-language-al-folio/commit/c1f168473f7cddb32c24404607e4fd181d189132 or the how you handled plugins to give additional functionality to liquid is super helpful as well thank you ^__^

You're welcome. Check the blog posts in the template demo, it is the best way to check what kind of stuff you can add to your site. In the end most of the stuff we added to the template is "web stuff" (not jekyll or ruby related). We only use liquid to include or not some specific code needed to make these libraries work. This helps avoid for example including mermaid.js in the about page, where we don't need it.

ctsstc commented 8 months ago

I was wondering with this bit of code, is it necessary to use the lookup, I didn't have to do that elsewhere, or is this specific to collections?

<a id="{{ site.data[site.active_lang].strings.categories[category] }}" href=".#{{ site.data[site.active_lang].strings.categories[category] }}">

https://github.com/george-gca/multi-language-al-folio/commit/5bb365a845a5165df27b93c9a69cd28236c2300e#diff-9f395b13d19af022840e74dd2cb4da4750d8818e6a41fad57ceae24f29cb5e7cR18

My Example

When I first started adding multiple languages to the navigation on the project I'm working on all I had to do was the following and it seems to pull the proper language without a code change.

Add Files

No Change in Code 🪄

{% for item in site.data.navigation %}
george-gca commented 8 months ago

@untra I can add my answers to the documentation. Where should I put them? In the site, in the README, or both?

george-gca commented 8 months ago

That specific code is responsible for the localization of the projects' categories, which in this screenshot is trabalho: image

I decided to make all localizations that are in layouts that should be shared between multiple pages to be made that way, using the strings.yml solution.

ctsstc commented 8 months ago

So far my i18n journey is going much better thanks to your example.

One thing to note, it does seem that it will grab the proper language for a collection if it exists when iterating through it with a for, but it does not seem to update the url on the collection item unfortunately.

george-gca commented 8 months ago

What do you mean?

ctsstc commented 8 months ago

Collection URLs

In this scenario the URL is always the default/english version for me, but it will pull, the translation for the item.title.

{% for item in filtered-portfolio %} 
    <a href="{{ item.url }}">item.title</a>
{% endfor %}

In my scenario we are firing off an AJAX request for the given URL, so I was able to pass along the currently active language through a data attribute and perform some logic when building out the URL before requesting it.

I was just looking at this again, should I instead maybe be using the relative_path instead to maintain the localization path? 🤔


One thing I just ran into with the /_data/LANG/strings.yml implementation is that Polyglot is normally great at defaulting back to the default language, but if strings.yml exists for a language but the key:value does not exist in that file, it will return an empty string rather than the default language unfortunately. This means there needs to be an exact mapping between all of the languages to utilize that pattern to avoid empty strings, or you need to be more granular with the implementation rather than storing everything into a single strings.yml to help avoid it a bit. You still will need a 1:1 lookup for any files that are defined.

george-gca commented 8 months ago

When in doubt, always print what is its value. For example:

{% for item in filtered-portfolio %} 
  <a href="{{ item.url }}">item.title</a>
  <script>
    console.log("{{ item.url }}");
    console.log("{{ item.url | relative_url }}");
  </script>
{% endfor %}

That's how I debug it.

but if strings.yml exists for a language but the key:value does not exist in that file, it will return an empty string rather than the default language unfortunately

For this case I wrote a plugin to check if the value exists in strings.yml. Check this answer.

untra commented 8 months ago

@untra I can add my answers to the documentation. Where should I put them? In the site, in the README, or both?

https://github.com/untra/polyglot#localized-sitedata

All of this is a great discussion, and you expand on this little section currently in the readme. If you can make this section a proper h2 and expand on it, adding in the words from here (great answer and example!) that'd be appreciated.

Additionally, your other example here is more worthy of a small blog post where you can describe the liquid strategy and challenge of translation tags. If you can write a small markdown post describing this approach, I can release it before the next release.

Also optional If you include a PT-br blog post copy as well, I might also expand the languages a little more. And happy to cross-promote your own blog and liquid examples. 🤝

Thank you for your help @george-gca you're a credit to the community!

george-gca commented 8 months ago

It is always good to contribute back after being helped a lot. I will create this content and submit a PR.

george-gca commented 8 months ago

I believe this can be closed now.