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

I18n and blog doesn't seem to cooperate when building the content collection #343

Open
andreamoro opened this issue May 5, 2017 · 23 comments

Comments

Projects
None yet
5 participants
@andreamoro
Copy link

commented May 5, 2017

Expected behaviour

With the I18n module active, I would expect the locale to be read and page_articles collection to be populated accordingly to the current locale

Actual behaviour

Regardless the current locale, the default language is always used hence the wrong collection of articles is returned

Steps to reproduce the problem

Using the gist below, navigate in the blog file under each of the locale folder, you will see the Italian version outputting the english title.

https://github.com/andreamoro/middleman-sprockets-test.git

Additional information

A possible workaround I may have found is to query directly the sitemap object.

  • Ruby version: 2.4
  • Middleman version: 4.2.1
  • Middleman Blog version: 4.0.1
  • I18n: 0.7.0 (I tried to use the 0.8.1, but there are some locked references that don't let me do it)
  • OS version: Mac OS X Sierra and Captain

A blog.local_articles(different-locale) produce always 0 results despite content is in the sitemap.

The issue above also creates problems with the pagination feature because of the erroneous dataset used. Although the right dataset could be queried with something like the below, in that case, the pagination will not be triggered anymore.

                   blog('otherlanguage').tags.each do |tag, articles|
                        articles.each do |article| 
                            puts article.data.title
                        end 
                    end
@andreamoro

This comment has been minimized.

Copy link
Author

commented May 8, 2017

A potential workaround is creating a specialised page with the blog: nameoftheblog clause in the FrontMatter.

Credit to epochwolf and this thread (appeared after several searches).
https://forum.middlemanapp.com/t/mulitple-blogs-specify-the-blog-name-blog-name-in-frontmatter-how/1588/2

@iwarner

This comment has been minimized.

Copy link
Member

commented May 13, 2017

@andreamoro Yes there does seem to be issue with the page_articles not taking into account the options provided

#242

I need to create more tests for this.

Do remember though that the i8n module used in core is not really supported in Blog and hacks need to happen - there should be more cross-over but blog still remains an extension.

@clstudio

This comment has been minimized.

Copy link

commented May 13, 2017

I can't get pagination, tags, and calendar to work with an i18n blog. The problem is thepage_articles method. blog.local_articles works fine. I'm trying to create a replication repo within the next days.

@iwarner how do you pass options to page_articles?

@andreamoro

This comment has been minimized.

Copy link
Author

commented May 14, 2017

@clstudio haven't tried your solution, but I believe you still need to do something like blog("blogID").... to get this working properly.

@clstudio

This comment has been minimized.

Copy link

commented May 14, 2017

@andreamoro It's not a solution :)
I'm having massive problems myself and no idea how to fix it.

@andreamoro

This comment has been minimized.

Copy link
Author

commented May 14, 2017

Welcome to the club then @clstudio .
I tell you what I've done to "fix" so far:

  1. two separate instances of blogcontroller, with the prefix getting the stuff into my desired local language

  2. two separate blog.lang file to act as the index page listing all articles for a given language. The logic of the file is the same, but in a partial. Difference is the frontmatter where a blog: bloginstanceID is specified to allow the blogcontroller and the page_articles.each collection to retrieve the correct list of articles

  3. hacking the locale extraction into a customhelper, looking at the current_resource.path so I can pass back to some internal functions to build links and stuff like that. Not optimal, but I'm not skilled enough to fork and fix the above, and I can't halt the project.

Hope the above can help.

@andreamoro

This comment has been minimized.

Copy link
Author

commented May 14, 2017

@iwarner what about having something in the after_configuration method that reads all the current path and overwrite both the :options=>{:locale=>:en, :lang=>:en}, :locals=>{:lang=>:en, :locale=>:en} settings?

Though, I suspect I may have been doing something wrong with too. Is the code below correct to have a locale in Italian?

  blogit.name = "blogit";
  blogit.prefix = 'it/blog'
  blogit.permalink = "{category}/:permalink" 
  blogit.layout = "Blog-inner"

I have been not expressly referencing the {:lang} variable, so it may be even me messing up things? However, the above configuration is the only one I could find to get things producing the path as expected.

Thanks

@clstudio

This comment has been minimized.

Copy link

commented May 15, 2017

@andreamoro I have 4+ language blog all nicely managed in a single blog controller via {lang}. I tried several times to break it into 4+ separate blogs but failed tremendously at each attempt. In my case it's best to keep it together and find another fix.

@andreamoro

This comment has been minimized.

Copy link
Author

commented May 15, 2017

@iwarner

This comment has been minimized.

Copy link
Member

commented May 15, 2017

@clstudio @andreamoro

I have created the following : https://iwarner.github.io/middleman-blog-test

With the source code here : https://github.com/iwarner/middleman-blog-test

This outlines some of the setup I do - please check out the config.rb

There are definite issues with the page_articles on the index page.

In config you can see I set locale on template files as such, but this needs to be better

so what we can do

  1. Check out the code and see what you think and if anything helps you
  2. Create pull requests for additional tests so we can see these in live action
  3. Use this as a running example of blog setup and configuration
  4. I will make this look prettier....

ready do

# Get all the french tags
sitemap.resources.select{ | d | d.data.template }.each do | resource |

  if resource.path[ 0...5 ] === locale.to_s

    # puts "Process #{ resource.path }"

    resource.add_metadata options: {
      locale: locale,
      lang:   locale
    }

  end

end

end

@clstudio

This comment has been minimized.

Copy link

commented May 15, 2017

@andreamoro The content resides as follows:

posts
  {lang}
    article.md
activate :blog do |blog|
    blog.permalink = "{lang}/{title}.html"
    blog.sources = "posts/{lang}/{year}-{month}-{day}-{title}.html"
    blog.default_extension = ".md"
    blog.tag_template = "tag.html"
    # blog.calendar_template = "calendar.html"

    # Enable pagination
    # blog.paginate = true
    # blog.per_page = 1000
    # blog.page_link = "page{num}"

    #blog.generate_tag_pages = false
end

@iwarner Thanks, that looks interesting, looping through each blog. Need a bit more time figuring this out.

@andreamoro

This comment has been minimized.

Copy link
Author

commented May 15, 2017

So kind of you @iwarner
Let me have a look into it and, yes I can see the ready do function already being a nice trick to make the locale working as expected (not sure it will overwrite values, but I assume you already have tested this).

@andreamoro

This comment has been minimized.

Copy link
Author

commented May 15, 2017

Ok, I think I nailed down the issue with my configuration, which requires the .preserve_locale = true.

By having this setting on, the blog extension seems to correctly import the locale setting from the i18n extension. Below the portion of my config.rb file for anybody else stumbling across this issue:

activate :blog do |blogen|
  blogen.name = "blogen";
  blogen.prefix = 'en/blog'
  blogen.permalink = "{category}/:permalink"
  blogen.preserve_locale = true
end

activate :blog do |blogit|
  blogit.name = "blogit";
  blogit.prefix = 'it/blog'
  blogit.permalink = "{category}/:permalink"
  blogit.preserve_locale = true
end

By doing so, I was able to achieve the following build output:

build 
   en
     blog
        myarticle
   it
     blog
        myarticle

whilst the source is something like

source
    content
        blog 
           article.it.html.markdown
           article.en.html.markdown

I will be exploring some more pieces from @iwarner configuration as it is more efficient having the loop to generate the blog instances.

@iwarner

This comment has been minimized.

Copy link
Member

commented May 15, 2017

Hiya

Can you check the __middleman sitemap and make sure Tags / Archive pages have the correct locale option

@andreamoro

This comment has been minimized.

Copy link
Author

commented May 15, 2017

I was not generating them, but I did a test for the Tags in the meantime.

Below the output.

Data	{:pageable=>true, :per_page=>6, :template=>true}
Locals	page_type, tagname, articles, blog_controller

The locale setting doesn't seem to be injected into the Tag, which is a bit annoying.

This doesn't work also when the blog: blogname is added, but at least in that circumstance the name is exposed in the frontmatter and some other loop mechanism can be done. However, I'd imagine that at that point the pagination system gets broken too.

@iwarner

This comment has been minimized.

Copy link
Member

commented May 15, 2017

Yeah this is why I have the routine to push in the locale options.

need to add template : true in the tag template frontmatter.

@andreamoro

This comment has been minimized.

Copy link
Author

commented May 15, 2017

So the ready do do add the locale to everything that has the template: true regardless the page type or just to Tags?

@iwarner

This comment has been minimized.

Copy link
Member

commented May 15, 2017

This is why I created the repo and test site :)

template: true - to files in here - https://github.com/iwarner/middleman-blog-test/tree/master/source/template

@andreamoro

This comment has been minimized.

Copy link
Author

commented May 15, 2017

Yes, you're right. Ok gotcha reading the code.

Aside from this, does the "better_error" (which I learned its existence from you today) works for you. I cannot get anything other than standard error page. Sorry for the deviation.

@iwarner

This comment has been minimized.

Copy link
Member

commented May 15, 2017

Make sure you also have

##
# Build-specific configuration
##
configure :development do
  # Better errors Gem
  use BetterErrors::Middleware
  BetterErrors.application_root = __dir__
end
@andreamoro

This comment has been minimized.

Copy link
Author

commented May 15, 2017

Yes, that's in place.
And I added also a set :show_exceptions, false that I got from an old post and previously identified as the cause of showing the "normal" error. No joy.

@GuillaumeSerrat

This comment has been minimized.

Copy link

commented Jan 19, 2018

@andreamoro

Not sure if this is still an issue for you but I managed to make it work based on the previous code.

Using the template: true in tags templates and category templates.

Config.rb

`# Make sure locals are available in all pages
ready do
sitemap.resources.select{ | d | d.data.template }.each do | resource |
extensions[:i18n].langs.each do |currentLang|
if resource.path[ 0...2 ] === currentLang.to_s
# puts "Process #{ resource.path[ 0...5 ] }"
# puts "Local match add metadata"

    resource.add_metadata options: {
      locale: currentLang,
      lang:   currentLang
    }
  else
    # puts "Resource: " + resource.path[ 0...5 ] + " didnt match: " + currentLang.to_s
  end
end

end
end`

activate :blog do |blog|
blog.name = "blogen"
blog.prefix = "en/blog"
blog.permalink = "{title}.html"
blog.sources = "{title}.html"
blog.paginate = true
blog.preserve_locale = true

blog.tag_template = "localizable/tag.html"
blog.calendar_template = "localizable/calendar.html"
blog.taglink = "tag/{tag}.html"

blog.custom_collections = {
category: {
link: '/category/{category}.html',
template: 'localizable/category.html'
}
}
end

activate :blog do |blog|
blog.name = "blogfr"
blog.prefix = "fr/blogue"
blog.permalink = "{title}.html"
blog.sources = "{title}.html"
blog.paginate = true
blog.preserve_locale = true

blog.tag_template = "localizable/tag.fr.html"
blog.calendar_template = "localizable/calendar.html"
blog.taglink = "tag/{tag}.html"

blog.custom_collections = {
category: {
link: '/categorie/{category}.html',
template: 'localizable/category.html'
}
}
end

activate :blog do |blog|
blog.name = "bloges"
blog.prefix = "es/blog"
blog.permalink = "{title}.html"
blog.sources = "{title}.html"
blog.paginate = true
blog.preserve_locale = true

blog.tag_template = "localizable/tag.es.html"
blog.calendar_template = "localizable/calendar.html"
blog.taglink = "tag/{tag}.html"

blog.custom_collections = {
category: {
link: '/categoria/{category}.html',
template: 'localizable/category.html'
}
}
end`

middleman-debug-i18n-using-custom-collections

middleman-debug-i18n-using-custom-collections-2

This is a lot of monkey patching and I feel like it should be supported as a default feature using Middleman / Middleman blog.

PS: I'm no ruby expert so please forgive my nooby code

@mrtndwrd

This comment has been minimized.

Copy link

commented Apr 24, 2018

Hope this helps someone. I've been having some trouble with pagination and multi-lingual blogs specifically. I was trying to make two separate blog index pages that show all the content of the blog of 1 language. I managed to fix it by following these pointers:

  • Providing the {lang} tag in your blog.sources configuration is essential. Otherwise the paginator will not know which blog posts correspond to which blog.
  • You can use blog: <blog_name> in your page's front matter to choose which blog controller is used for a page. This does not only count for blog posts, but also for my index page.

We've got some other specifics in our configuration which also might help you. We have defined a locales variable where the first is the default (mounted at root) and the next ones are mounted at /<lang>.

locales = [:en, :nl] 
locales.each_with_index do | locale, index |
  # Blog
  activate :blog do | blog |
    # Locale path: first locale is mounted at root
    path = index > 0 ? "#{locale}/" : ""
    blog.name      = "blog_#{locale}"
    blog.permalink = "#{path}blog/{year}/{month}/{day}/{title}.html"

    # See "Edit 3" to understand why this is so weird.
    # blog.sources = "blog/{lang}/{year}-{month}-{day}-{engtitle}.html"
    blog.sources = "blog/#{locale}/{lang}/{year}-{month}-{day}-{engtitle}.html"
    blog.layout    = "blog"

    # Pagination
    blog.paginate  = true
    blog.page_link = "page/{num}"
    blog.per_page  = 15

    # Calendar
    blog.calendar_template = "blog/calendar.html"
    blog.year_link         = "#{path}blog/{year}.html"
    blog.month_link        = "#{path}blog/{year}/{month}.html"
    blog.day_link          = "#{path}blog/{year}/{month}/{day}.html"

    # Tags
    blog.tag_template = "blog/tag.html"
    blog.taglink      = "#{path}blog/tag/{tag}.html"
    # Use the global Middleman I18n.locale instead of the lang in the
    # article's frontmatter
    blog.preserve_locale = true

    blog.custom_collections = {
      author: {
        link: "#{path}blog/author/{author}.html",
        template: "blog/author.html"
      }
    }
  end
end

Using this configuration also works for the custom author collection! 😃

Edit: I have to admit that I'm also still using this helper function to fix the locale in blog overview pages, which might help cause the fact that this works:

  def fix_locale(controller)
    I18n.locale = controller.name.to_s.sub("blog_", "")
  end

Edit 2: This still doesn't work because now all files are added to the last blog (in this case blog_nl), so all blog posts get an URL starting with nl/... Working on a fix...

Edit 3: I found a solution, but it is not as pretty as I had hoped. I changed this line in config.rb

blog.sources = "blog/{lang}/{year}-{month}-{day}-{engtitle}.html"

to this:

blog.sources = "blog/#{locale}/{lang}/{year}-{month}-{day}-{engtitle}.html"

I had to move all my blog posts from source/blog/<lang>/<name>.html.md to source/blog/<lang>/<lang>/<name>.html.md to make this work. The first <lang> folder now helps distinguish which files need to be in which blog. The subfolder now helps middleman-blog parse the {lang} parameter so internationalisation works as expected.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.