middleman-blog icon indicating copy to clipboard operation
middleman-blog copied to clipboard

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

Open andreamoro opened this issue 7 years ago • 24 comments

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 avatar May 05 '17 20:05 andreamoro

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

andreamoro avatar May 08 '17 08:05 andreamoro

@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.

iwarner avatar May 13 '17 17:05 iwarner

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?

clstudio avatar May 13 '17 18:05 clstudio

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

andreamoro avatar May 14 '17 12:05 andreamoro

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

clstudio avatar May 14 '17 13:05 clstudio

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 avatar May 14 '17 13:05 andreamoro

@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

andreamoro avatar May 14 '17 13:05 andreamoro

@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.

clstudio avatar May 15 '17 09:05 clstudio

That's what I'm trying to achieve, but was unsuccessful so far.

Does your content reside into a single folder, with the language identifiable via the path? Would you mind sharing your structure and config.rb blog section?

Cheers

On 15 May 2017 10:00, "clstudio" [email protected] wrote:

@andreamoro https://github.com/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.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/middleman/middleman-blog/issues/343#issuecomment-301417257, or mute the thread https://github.com/notifications/unsubscribe-auth/AFA1h16EsQPkHVuFs_hDal2dagxBvjZsks5r6BQngaJpZM4NSZvn .

andreamoro avatar May 15 '17 09:05 andreamoro

@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

iwarner avatar May 15 '17 11:05 iwarner

@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.

clstudio avatar May 15 '17 11:05 clstudio

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 avatar May 15 '17 11:05 andreamoro

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.

andreamoro avatar May 15 '17 15:05 andreamoro

Hiya

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

iwarner avatar May 15 '17 15:05 iwarner

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.

andreamoro avatar May 15 '17 16:05 andreamoro

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

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

iwarner avatar May 15 '17 16:05 iwarner

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

andreamoro avatar May 15 '17 16:05 andreamoro

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

iwarner avatar May 15 '17 16:05 iwarner

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.

andreamoro avatar May 15 '17 16:05 andreamoro

Make sure you also have

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

iwarner avatar May 15 '17 16:05 iwarner

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.

andreamoro avatar May 15 '17 16:05 andreamoro

@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

GuillaumeSerrat avatar Jan 19 '18 22:01 GuillaumeSerrat

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! :smiley:

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.

mrtndwrd avatar Apr 24 '18 09:04 mrtndwrd

ℹ️ This issue is stale because it has been open for more than 90 days with no activity. It will be closed in 30 days if no further activity occurs. Thank you for your contributions.

markets avatar Apr 15 '24 18:04 markets