diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index f301ae8e..ec462521 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -22,8 +22,10 @@ class ApplicationController < ActionController::Base def find_post(site) id = params[:post_id] || params[:id] + lang = params.fetch(:lang, I18n.locale.to_s) + posts = site.posts_for(lang) - site.posts.find do |p| + posts.find do |p| p.id == id end end diff --git a/app/controllers/posts_controller.rb b/app/controllers/posts_controller.rb index 565f4350..7c099311 100644 --- a/app/controllers/posts_controller.rb +++ b/app/controllers/posts_controller.rb @@ -2,8 +2,10 @@ class PostsController < ApplicationController before_action :authenticate! def index - @site = find_site + @site = find_site @category = session[:category] = params.dig(:category) + @lang = params.fetch(:lang, I18n.locale.to_s) + @posts = @site.posts_for(@lang) end def show diff --git a/app/models/post.rb b/app/models/post.rb index e2950a89..203303c1 100644 --- a/app/models/post.rb +++ b/app/models/post.rb @@ -15,7 +15,7 @@ require 'jekyll/utils' # datos y los sincroniza al momento de leer y de escribir el Document. class Post attr_accessor :content, :front_matter - attr_reader :post, :site, :errors, :old_post + attr_reader :post, :site, :errors, :old_post, :lang REJECT_FROM_DATA = %w[excerpt].freeze # datos que no tienen que terminar en el front matter @@ -24,7 +24,7 @@ class Post # Trabajar con posts. Si estamos creando uno nuevo, el **site** y # el **front_matter** son necesarios, sino, **site** y **post**. # XXX chequear que se den las condiciones - def initialize(site:, post: nil, front_matter: {}) + def initialize(site:, post: nil, front_matter: {}, lang: nil) unless site.is_a?(Site) raise ArgumentError, I18n.t('errors.argument_error', argument: :site, class: Site) @@ -36,6 +36,7 @@ class Post class: Jekyll::Document) end + @lang = lang || I18n.locale.to_s @site = site @post = post # los errores tienen que ser un hash para que @@ -62,6 +63,21 @@ class Post @post.nil? || !File.exist?(@post.try(:path)) end + # Determina si fue traducido, buscando los slugs de su front_matter + # lang en otras colecciones + def translated? + get_front_matter('lang').present? + end + + def translations + @translations ||= get_front_matter('lang').map do |lang, id| + next if lang == @lang + @site.posts_for(lang).find do |p| + p.id == id + end + end.compact + end + # Guarda los cambios. # # Recién cuando vamos a guardar creamos el Post, porque ya tenemos diff --git a/app/models/site.rb b/app/models/site.rb index 1d1342b5..2f51e8b1 100644 --- a/app/models/site.rb +++ b/app/models/site.rb @@ -10,11 +10,20 @@ class Site @path = path || @jekyll.config['source'] end + # Determina si el sitio está en varios idiomas + def i18n? + @jekyll.config.dig('i18n').present? + end + # Obtener el nombre del sitio def name @name ||= @jekyll.config['source'].split('/').last end + def name_with_i18n(lang) + [name, lang].join('/') + end + # El id es el sitio sin puntos, para no confundir al routeador de # rails def id @@ -50,16 +59,32 @@ class Site end @jekyll.config - end - # Los posts de este sitio + # Los posts de este sitio, si el sitio está traducido, trae los posts + # del idioma actual, porque _posts va a estar vacío def posts - return @posts if @posts + @posts ||= if i18n? + posts_for(I18n.locale.to_s) + else + posts_for('posts') + end + end - Rails.logger.info 'Procesando posts' + # Obtiene todos los posts de una colección determinada + # + # Devuelve nil si la colección no existe + def posts_for(collection) + return unless @jekyll.config['collections'].key? collection - if @jekyll.posts.docs.empty? + # TODO tal vez no necesitamos esta magia + instance = instance_variable_get("@#{collection}") + return instance if instance + + Rails.logger.info "Procesando #{collection}" + + col = @jekyll.collections[collection].docs + if col.empty? @jekyll.read # Queremos saber cuantas veces releemos los articulos Rails.logger.info 'Leyendo articulos' @@ -67,9 +92,9 @@ class Site # Los convertimos a una clase intermedia capaz de acceder a sus # datos y modificarlos - @posts = @jekyll.posts.docs.map do |post| - Post.new(site: self, post: post) - end + instance_variable_set("@#{collection}", col.map do |post| + Post.new(site: self, post: post, lang: collection) + end) end def categories @@ -188,6 +213,15 @@ class Site config[unneeded] = [] if config.key? unneeded end + # Si estamos usando nuestro propio plugin de i18n, los posts están + # en "colecciones" + i18n = config.dig('i18n') + if i18n + i18n.each do |i| + config['collections'][i] = {} + end + end + Jekyll::Site.new(config) end diff --git a/app/views/posts/index.haml b/app/views/posts/index.haml index d8020264..fa97a1dc 100644 --- a/app/views/posts/index.haml +++ b/app/views/posts/index.haml @@ -1,9 +1,10 @@ .row .col - = render 'layouts/breadcrumb', crumbs: [ link_to(t('sites.index'), sites_path), @site.name, link_to(t('posts.index'), site_posts_path(@site)), @category ] + = render 'layouts/breadcrumb', + crumbs: [ link_to(t('sites.index'), sites_path), @site.name, link_to(t('posts.index'), site_posts_path(@site)), @category ] .row .col - %h1= @site.name + %h1= @site.name_with_i18n(@lang) .row .col @@ -12,18 +13,34 @@ .row .col - %table.table.table-condensed.table-striped - %tbody - - @site.posts.each do |post| - - if @category - - next unless post.categories.include?(@category) - - direction = post.get_front_matter(:dir) - %tr - %td{class: direction} - = link_to post.title, site_post_path(@site, post) - %br - %small - - post.categories.each do |c| - = link_to c, site_posts_path(@site, category: c) - %td= post.date.strftime('%F') - %td= link_to t('post.edit'), edit_site_post_path(@site, post) + - if @posts.present? + %table.table.table-condensed.table-striped + %tbody + - @posts.each do |post| + - if @category + -# saltearse el post a menos que esté en la categoría + -# por la que estamos filtrando + - next unless post.categories.include?(@category) + -# establecer la direccion del texto + - direction = post.get_front_matter(:dir) + %tr + %td{class: direction} + = link_to post.title, site_post_path(@site, post) + %br + %small + - post.categories.each do |c| + = link_to c, site_posts_path(@site, category: c) + %td + - if post.translations + %small + - post.translations.each do |pt| + = link_to pt.title, site_post_path(@site, pt, lang: pt.lang) + %span.badge.badge-info= t("i18n.#{pt.lang}") + %br + + %td= post.date.strftime('%F') + %td= link_to t('post.edit'), + edit_site_post_path(@site, post), + class: 'btn btn-info' + - else + %h2= t('posts.none')