diff --git a/app/controllers/posts_controller.rb b/app/controllers/posts_controller.rb index 26b7b048..a4c1e801 100644 --- a/app/controllers/posts_controller.rb +++ b/app/controllers/posts_controller.rb @@ -26,7 +26,7 @@ class PostsController < ApplicationController @post = Post.new(site: @site, front_matter: post_params.to_hash) if @post.save - redirect_to site_posts_path(@site) + redirect_to site_posts_path(@site, lang: @lang) else render 'posts/new' end @@ -47,7 +47,7 @@ class PostsController < ApplicationController @post.update_attributes(p) if @post.save - redirect_to site_posts_path(@site, category: session[:category]) + redirect_to site_posts_path(@site, category: session[:category], lang: @lang) else render 'posts/edit' end diff --git a/app/models/post.rb b/app/models/post.rb index 63b9a166..dc74be1e 100644 --- a/app/models/post.rb +++ b/app/models/post.rb @@ -77,7 +77,11 @@ class Post end def translations - @translations ||= get_front_matter('lang').map do |lang, id| + @translations ||= find_translations + end + + def find_translations + get_front_matter('lang').map do |lang, id| next if lang == @lang @site.posts_for(lang).find do |p| p.id == id @@ -91,7 +95,6 @@ class Post # todos los datos para escribir el archivo, que es la condición # necesaria para poder crearlo :P def save - binding.pry cleanup! return false unless valid? @@ -116,6 +119,10 @@ class Post get_front_matter 'date' end + def date_as_string + date.strftime('%F') + end + def tags get_front_matter 'tags' end @@ -147,6 +154,13 @@ class Post @post.try(:basename) != basename_from_front_matter end + def slug_changed? + @post.data.dig('slug') != slug + end + + # Trae el contenido del post, si no lo seteamos ya. O sea que si solo + # enviamos actualizaciones al front matter, debería traer el contenido + # del post sin cambios def content @content ||= @post.try :content end @@ -160,8 +174,8 @@ class Post # Requisitos para que el post sea válido def validate - add_error validate: I18n.t('posts.errors.date') unless get_front_matter('date').is_a? Time - add_error validate: I18n.t('posts.errors.title') if get_front_matter('title').blank? + add_error validate: I18n.t('posts.errors.date') unless date.is_a? Time + add_error validate: I18n.t('posts.errors.title') if title.blank? # TODO verificar que el id sea único end @@ -232,11 +246,9 @@ class Post # Obtiene el nombre del archivo a partir de los datos que le # pasemos def basename_from_front_matter - date = get_front_matter('date').strftime('%F') - slug = get_front_matter('slug') - ext = get_front_matter('ext') || '.markdown' + ext = get_front_matter('ext') || '.markdown' - "#{date}-#{slug}#{ext}" + "#{date_as_string}-#{slug}#{ext}" end # Toma los datos del front matter local y los mueve a los datos @@ -263,6 +275,26 @@ class Post clean_content! slugify_title! remove_empty_front_matter! + update_lang_front_matter! + update_translations! + end + + # Setea el propio idioma en el front_matter de slugs + def update_lang_front_matter! + return unless translated? + + @front_matter['lang'][@lang] = slug + end + + # Busca las traducciones y actualiza el frontmatter si es necesario + def update_translations! + return unless translated? + return unless slug_changed? + + find_translations.each do |post| + post.update_attributes(lang: get_front_matter('lang')) + post.save + end end def remove_empty_front_matter! @@ -301,13 +333,17 @@ class Post end # Genera el post con front matter, menos los campos que no necesitamos - # que estén en el front matter + # que estén en el front matter. + # + # El contenido se toma de `content` en lugar de `@content`, para poder + # obtener el contenido por defecto si es que no lo enviamos + # modificaciones, como en `update_translations!` def full_content yaml = @front_matter.reject do |k,_| REJECT_FROM_FRONT_MATTER.include? k end - "#{yaml.to_yaml}---\n\n#{@content}" + "#{yaml.to_yaml}---\n\n#{content}" end def add_error(hash) @@ -331,14 +367,14 @@ class Post def things_to_arrays! [:tags,:categories].each do |c| thing = @front_matter.dig(c.to_s) + next if thing.blank? next if thing.is_a? Array @front_matter[c.to_s] = thing.split(',').map(&:strip) end end def slugify_title! - if get_front_matter('slug').blank? - title = get_front_matter('title') + if slug.blank? @front_matter['slug'] = Jekyll::Utils.slugify(title) end end diff --git a/app/views/posts/show.haml b/app/views/posts/show.haml index 8d9eef23..16ff9470 100644 --- a/app/views/posts/show.haml +++ b/app/views/posts/show.haml @@ -11,6 +11,11 @@ .col %h1{class: @post.get_front_matter(:dir)}= @post.title + %p + - translations = @post.translations.map do |translation| + - link_to translation.title, site_post_path(@site, translation, lang: translation.lang) + = raw translations.join(' / ') + .row .col = link_to t('posts.edit'), diff --git a/doc/i18n.md b/doc/i18n.md index 7cd1e8da..e64394a5 100644 --- a/doc/i18n.md +++ b/doc/i18n.md @@ -34,3 +34,23 @@ nuevos en ese idioma. como se puede mantener el lang actualizado para todos los posts? recorrer cada post y modificarle el front matter y salvarlo? +cada post tiene un hash `lang: { idioma: 'slug' }`, que contiene todas +las traducciones de su slug (vendrian a ser las relaciones +has_and_belongs_to_many (habtm) en active record) e incluso su propio +slug: + +``` +post.front_matter['lang'] = { + es: 'slug-en-castellano', + en: 'english-slug' +} +``` + +entonces si el idioma es castellano y el **slug cambia**, recorremos +todos los posts y evitamos el idioma actual, actualizando el front +matter de los demas, de forma que la relacion se mantenga. + +esto seria mas facil de hacer en un solo lado teniendo un +`_data/post_relations.yml` o algo asi que tenga una sola vez todas las +traducciones de los slugs, pero requiere hacer cambios en themes ya +existentes