middleman / middleman-blog

Blog Engine Extension for Middleman
https://middlemanapp.com
MIT License
325 stars 179 forks source link

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

Open andreamoro opened 7 years ago

andreamoro commented 7 years ago

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.

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 commented 7 years ago

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 commented 7 years ago

@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 commented 7 years ago

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 commented 7 years ago

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

clstudio commented 7 years ago

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

andreamoro commented 7 years ago

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 commented 7 years ago

@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 commented 7 years ago

@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 commented 7 years ago

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" notifications@github.com 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 .

iwarner commented 7 years ago

@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 commented 7 years ago

@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 commented 7 years ago

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 commented 7 years ago

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 commented 7 years ago

Hiya

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

andreamoro commented 7 years ago

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 commented 7 years ago

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 commented 7 years ago

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

iwarner commented 7 years ago

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 commented 7 years ago

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 commented 7 years ago

Make sure you also have

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

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 commented 6 years ago

@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 commented 6 years ago

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:

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.

markets commented 4 months ago

ℹ️ 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.