diff --git a/Gemfile b/Gemfile index d03c9d6..d50f4f8 100644 --- a/Gemfile +++ b/Gemfile @@ -1,7 +1,5 @@ source 'https://rubygems.org' - - ################################################################################ # # Gemspec @@ -13,10 +11,6 @@ source 'https://rubygems.org' gemspec - - - - ################################################################################ # # Default @@ -26,10 +20,6 @@ gemspec #gem "jekyll", "~> 2.0" # Uncoment to use Jekyll 2 - - - - ################################################################################ # # Groups @@ -40,15 +30,15 @@ gemspec # development ####################################### #group :development do -# +# #end - ####################################### # test ####################################### group :test do - gem "jekyll-paginate" - gem "redcarpet" + gem 'jekyll-paginate' + gem 'redcarpet' + gem 'minitest' end diff --git a/README.md b/README.md index 9f79a27..3d027bf 100644 --- a/README.md +++ b/README.md @@ -85,7 +85,7 @@ Or install it yourself as: `$ gem install jekyll-multiple-languages-plugin` To activate the plugin add it to the Jekyll `_config.yml` file, under the `gems` option: ```ruby -gems: +gems: - jekyll-multiple-languages-plugin ``` See the [Jekyll configuration documentation](http://jekyllrb.com/docs/configuration) for details. @@ -115,8 +115,9 @@ $ git pull origin master ## 4. Configuration -### 4.1. _config.yml -Add the languages available in your website into your _config.yml (obligatory): +### 4.1. \_config.yml + +Add the languages available in your website into your \_config.yml (obligatory): ```yaml languages: ["sv", "en", "de", "fr"] @@ -129,23 +130,24 @@ To avoid redundancy, it is possible to exclude files and folders from being copi ```yaml exclude_from_localizations: ["javascript", "images", "css"] ``` + In code, these specific files should be referenced via `baseurl_root`. E.g. -``` +```html ``` ### 4.2. Folder structure Create a folder called `_i18n` and add sub-folders for each language, using the same names used on the `languages` setting on the `_config.yml`: - - /_i18n/sv.yml - - /_i18n/en.yml - - /_i18n/de.yml - - /_i18n/fr.yml - - /_i18n/sv/pagename/blockname.md - - /_i18n/en/pagename/blockname.md - - /_i18n/de/pagename/blockname.md - - /_i18n/fr/pagename/blockname.md + - /\_i18n/sv.yml + - /\_i18n/en.yml + - /\_i18n/de.yml + - /\_i18n/fr.yml + - /\_i18n/sv/pagename/blockname.md + - /\_i18n/en/pagename/blockname.md + - /\_i18n/de/pagename/blockname.md + - /\_i18n/fr/pagename/blockname.md @@ -352,11 +354,11 @@ permalink: /about/ {% translate_file about/about.md %} ``` -Then, create a file named `about.md` under `_i18n/en` with the English content. Repeat this for the other languages (_i18n/es/about.md ...). When running the website, visit the address `http://localhost:4000/about` to see the English version, `http://localhost:4000/es/about` for the Spanish one, etc. - +Then, create a file named `about.md` under `_i18n/en` with the English content. Repeat this for the other languages (\_i18n/es/about.md ...). When running the website, visit the address `http://localhost:4000/about` to see the English version, `http://localhost:4000/es/about` for the Spanish one, etc. ## 8. Changelog + * 1.5.1 * Fix a bug (#70) where `site.static_files` would be empty on subsites if `exclude_from_localizations` is used. * Some overall project enhancements and minor fixes. @@ -419,6 +421,16 @@ Then, create a file named `about.md` under `_i18n/en` with the English content. 4. Push to the branch (`git push origin my-new-feature`) 5. Create a new Pull Request +### Test + +For testing purpose: + + rake test + +For test the building: + + rake build + ### Contributors | User | Contribution | | :----------------------------------------------- | :----------------------------------- | diff --git a/Rakefile b/Rakefile index 5bb6a9e..9dfd31d 100644 --- a/Rakefile +++ b/Rakefile @@ -1,21 +1,15 @@ require "bundler/gem_tasks" - - -####################################### -# default -####################################### task :default => [:test] - - -####################################### -# test -####################################### -# A simple test which buils the example site. desc "Run tests" -task :test do + +task :build do cd "example" do sh "bundle exec jekyll build" end end + +task :test do + sh "ruby test/base_test.rb" +end diff --git a/example/_config.yml b/example/_config.yml index f763c18..3bfe595 100644 --- a/example/_config.yml +++ b/example/_config.yml @@ -13,7 +13,7 @@ paginate_path: "/pagination/page:num/" # Plugins -gems: +plugins: - jekyll-multiple-languages-plugin - jekyll-paginate @@ -21,4 +21,4 @@ gems: # jekyll-multiple-languages-plugin settings: languages: ["it", "en", "es"] -exclude_from_localizations: ["javascript", "images", "css", "scripts", "favicon.ico"] +exclude_from_localizations: ["javascript", "images", "css", "scripts", "favicon.ico", "robots.txt"] diff --git a/example/robots.txt b/example/robots.txt new file mode 100644 index 0000000..a99943c --- /dev/null +++ b/example/robots.txt @@ -0,0 +1,4 @@ +--- +permalink: robots.txt +--- +Test for dynamic content that have to be excluded from localization folders. diff --git a/lib/custom_tags.rb b/lib/custom_tags.rb new file mode 100644 index 0000000..34fb2ed --- /dev/null +++ b/lib/custom_tags.rb @@ -0,0 +1,164 @@ +module Jekyll + + # Implements the plugin Liquid Tags and/or Filters + + ############################################################################## + # class LocalizeTag + # + # Localization by getting localized text from YAML files. + # User must use the "t" or "translate" liquid tags. + ############################################################################## + class LocalizeTag < Liquid::Tag + + def initialize(tag_name, key, tokens) + super + @key = key.strip + end + + def render(context) + if "#{context[@key]}" != "" # Check for page variable + key = "#{context[@key]}" + else + key = @key + end + + key = Liquid::Template.parse(key).render(context) # Parses and renders some Liquid syntax on arguments (allows expansions) + + site = context.registers[:site] # Jekyll site object + + lang = site.config['lang'] + + unless site.parsed_translations.has_key?(lang) + puts "Loading translation from file #{site.source}/_i18n/#{lang}.yml" + site.parsed_translations[lang] = YAML.load_file("#{site.source}/_i18n/#{lang}.yml") + end + + translation = site.parsed_translations[lang].access(key) if key.is_a?(String) + + if translation.nil? or translation.empty? + translation = site.parsed_translations[site.config['default_lang']].access(key) + + puts "Missing i18n key: #{lang}:#{key}" + puts "Using translation '%s' from default language: %s" %[translation, site.config['default_lang']] + end + + translation + end + end + + + ############################################################################## + # class LocalizeInclude + # + # Localization by including whole files that contain the localization text. + # User must use the "tf" or "translate_file" liquid tags. + ############################################################################## + module Tags + class LocalizeInclude < IncludeTag + + def render(context) + if "#{context[@file]}" != "" # Check for page variable + file = "#{context[@file]}" + else + file = @file + end + + file = Liquid::Template.parse(file).render(context) # Parses and renders some Liquid syntax on arguments (allows expansions) + + site = context.registers[:site] # Jekyll site object + + includes_dir = File.join(site.source, '_i18n/' + site.config['lang']) + + validate_file_name(file) + + Dir.chdir(includes_dir) do + choices = Dir['**/*'].reject { |x| File.symlink?(x) } + + if choices.include?( file) + source = File.read(file) + partial = Liquid::Template.parse(source) + + context.stack do + context['include'] = parse_params( context) if @params + contents = partial.render(context) + ext = File.extname(file) + + converter = site.converters.find { |c| c.matches(ext) } + contents = converter.convert(contents) unless converter.nil? + + contents + end + else + raise IOError.new "Included file '#{file}' not found in #{includes_dir} directory" + end + + end + end + end + end + + + + ############################################################################## + # class LocalizeLink + # + # Creates links or permalinks for translated pages. + # User must use the "tl" or "translate_link" liquid tags. + ############################################################################## + class LocalizeLink < Liquid::Tag + + def initialize(tag_name, key, tokens) + super + @key = key + end + + def render(context) + if "#{context[@key]}" != "" # Check for page variable + key = "#{context[@key]}" + else + key = @key + end + + key = Liquid::Template.parse(key).render(context) # Parses and renders some Liquid syntax on arguments (allows expansions) + + site = context.registers[:site] # Jekyll site object + + key = key.split + namespace = key[0] + lang = key[1] || site.config[ 'lang'] + default_lang = site.config['default_lang'] + baseurl = site.baseurl + pages = site.pages + url = ""; + + if default_lang != lang + baseurl = baseurl + "/" + lang + end + + for p in pages + unless p['namespace'].nil? + page_namespace = p['namespace'] + + if namespace == page_namespace + permalink = p['permalink_'+lang] || p['permalink'] + url = baseurl + permalink + end + end + end + + url + end + end +end + + + +################################################################################ +# Liquid tags definitions + +Liquid::Template.register_tag('t', Jekyll::LocalizeTag ) +Liquid::Template.register_tag('translate', Jekyll::LocalizeTag ) +Liquid::Template.register_tag('tf', Jekyll::Tags::LocalizeInclude) +Liquid::Template.register_tag('translate_file', Jekyll::Tags::LocalizeInclude) +Liquid::Template.register_tag('tl', Jekyll::LocalizeLink ) +Liquid::Template.register_tag('translate_link', Jekyll::LocalizeLink ) diff --git a/lib/jekyll-multiple-languages-plugin.rb b/lib/jekyll-multiple-languages-plugin.rb index 1cbabf6..2d8a79f 100644 --- a/lib/jekyll-multiple-languages-plugin.rb +++ b/lib/jekyll-multiple-languages-plugin.rb @@ -10,477 +10,45 @@ =end - - -require_relative "plugin/version" +require_relative 'plugin/version' +require_relative 'overwrite_jekyll/site' +require_relative 'overwrite_jekyll/page' +require_relative 'overwrite_jekyll/post' +require_relative 'overwrite_jekyll/post_reader' +require_relative 'overwrite_jekyll/document' +require_relative 'overwrite_jekyll/hash_custom' + +require_relative 'custom_tags' +require_relative 'tools/path_equivalent' +require_relative 'tools/remover' module Jekyll - #***************************************************************************** - # :site, :post_render hook - #***************************************************************************** - Jekyll::Hooks.register :site, :post_render do |site, payload| - - # Removes all static files that should not be copied to translated sites. - #=========================================================================== + Jekyll::Hooks.register(:site, :post_render) do |site, payload| + default_lang = payload["site"]["default_lang"] - current_lang = payload["site"][ "lang"] - + current_lang = payload["site"]["lang"] + static_files = payload["site"]["static_files"] exclude_paths = payload["site"]["exclude_from_localizations"] - - + pages = payload["site"]["pages"] + + if default_lang != current_lang + # Remove excluded files from static files static_files.delete_if do |static_file| - + # static_file is a Jekyll::StaticFile # Remove "/" from beginning of static file relative path - static_file_r_path = static_file.instance_variable_get(:@relative_path).dup - static_file_r_path[0] = '' - - exclude_paths.any? do |exclude_path| - Pathname.new(static_file_r_path).descend do |static_file_path| - break(true) if (Pathname.new(exclude_path) <=> static_file_path) == 0 - end - end + static_file_relative_path = static_file.instance_variable_get(:@relative_path).dup + static_file_relative_path[0] = '' + MultipleLanguagePluginTools::RemoverStaticFiles.go static_file_relative_path, exclude_paths end - end - - #=========================================================================== - - end - - - - ############################################################################## - # class Site - ############################################################################## - class Site - - attr_accessor :parsed_translations # Hash that stores parsed translations read from YAML files. - - alias :process_org :process - - #====================================== - # process - # - # Reads Jekyll and plugin configuration parameters set on _config.yml, sets - # main parameters and processes the website for each language. - #====================================== - def process - # Check if plugin settings are set, if not, set a default or quit. - #------------------------------------------------------------------------- - self.parsed_translations ||= {} - - self.config['exclude_from_localizations'] ||= [] - - if ( !self.config['languages'] or - self.config['languages'].empty? or - !self.config['languages'].all? - ) - puts 'You must provide at least one language using the "languages" setting on your _config.yml.' - - exit - end - - - # Variables - #------------------------------------------------------------------------- - - # Original Jekyll configurations - baseurl_org = self.config[ 'baseurl' ] # Baseurl set on _config.yml - dest_org = self.dest # Destination folder where the website is generated - - # Site building only variables - languages = self.config['languages'] # List of languages set on _config.yml - - # Site wide plugin configurations - self.config['default_lang'] = languages.first # Default language (first language of array set on _config.yml) - self.config[ 'lang'] = languages.first # Current language being processed - self.config['baseurl_root'] = baseurl_org # Baseurl of website root (without the appended language code) - self.config['translations'] = self.parsed_translations # Hash that stores parsed translations read from YAML files. Exposes this hash to Liquid. - - - # Build the website for default language - #------------------------------------------------------------------------- - puts "Building site for default language: \"#{self.config['lang']}\" to: #{self.dest}" - - process_org - - - # Build the website for the other languages - #------------------------------------------------------------------------- - - # Remove .htaccess file from included files, so it wont show up on translations folders. - self.include -= [".htaccess"] - - languages.drop(1).each do |lang| - - # Language specific config/variables - @dest = dest_org + "/" + lang - self.config['baseurl'] = baseurl_org + "/" + lang - self.config['lang'] = lang - - puts "Building site for language: \"#{self.config['lang']}\" to: #{self.dest}" - - process_org - end - - # Revert to initial Jekyll configurations (necessary for regeneration) - self.config[ 'baseurl' ] = baseurl_org # Baseurl set on _config.yml - @dest = dest_org # Destination folder where the website is generated - - puts 'Build complete' - end - - - - if Gem::Version.new(Jekyll::VERSION) < Gem::Version.new("3.0.0") - alias :read_posts_org :read_posts - - #====================================== - # read_posts - #====================================== - def read_posts(dir) - translate_posts = !self.config['exclude_from_localizations'].include?("_posts") - - if dir == '' && translate_posts - read_posts("_i18n/#{self.config['lang']}/") - else - read_posts_org(dir) - end - + # Remove excluded files from pages (ex: dynamic robots.txt) + pages.delete_if do |page| + exclude_paths.include? page.name end end end - - - ############################################################################## - # class PostReader - ############################################################################## - class PostReader - - if Gem::Version.new(Jekyll::VERSION) >= Gem::Version.new("3.0.0") - alias :read_posts_org :read_posts - - #====================================== - # read_posts - #====================================== - def read_posts(dir) - translate_posts = !site.config['exclude_from_localizations'].include?("_posts") - if dir == '' && translate_posts - read_posts("_i18n/#{site.config['lang']}/") - else - read_posts_org(dir) - end - end - end - end - - - - ############################################################################## - # class Page - ############################################################################## - class Page - - #====================================== - # permalink - #====================================== - def permalink - return nil if data.nil? || data['permalink'].nil? - - if site.config['relative_permalinks'] - File.join(@dir, data['permalink']) - else - # Look if there's a permalink overwrite specified for this lang - data['permalink_'+site.config['lang']] || data['permalink'] - end - - end - end - - - - ############################################################################## - # class Post - ############################################################################## - class Post - - if Gem::Version.new(Jekyll::VERSION) < Gem::Version.new("3.0.0") - alias :populate_categories_org :populate_categories - - #====================================== - # populate_categories - # - # Monkey patched this method to remove unwanted strings - # ("_i18n" and language code) that are prepended to posts categories - # because of how the multilingual posts are arranged in subfolders. - #====================================== - def populate_categories - categories_from_data = Utils.pluralized_array_from_hash(data, 'category', 'categories') - self.categories = ( - Array(categories) + categories_from_data - ).map {|c| c.to_s.downcase}.flatten.uniq - - self.categories.delete("_i18n") - self.categories.delete(site.config['lang']) - - return self.categories - end - end - end - - - - ############################################################################## - # class Document - ############################################################################## - class Document - - if Gem::Version.new(Jekyll::VERSION) >= Gem::Version.new("3.0.0") - alias :populate_categories_org :populate_categories - - #====================================== - # populate_categories - # - # Monkey patched this method to remove unwanted strings - # ("_i18n" and language code) that are prepended to posts categories - # because of how the multilingual posts are arranged in subfolders. - #====================================== - def populate_categories - data['categories'].delete("_i18n") - data['categories'].delete(site.config['lang']) - - merge_data!({ - 'categories' => ( - Array(data['categories']) + Utils.pluralized_array_from_hash(data, 'category', 'categories') - ).map(&:to_s).flatten.uniq - }) - end - end - end - - - - #----------------------------------------------------------------------------- - # - # The next classes implements the plugin Liquid Tags and/or Filters - # - #----------------------------------------------------------------------------- - - - ############################################################################## - # class LocalizeTag - # - # Localization by getting localized text from YAML files. - # User must use the "t" or "translate" liquid tags. - ############################################################################## - class LocalizeTag < Liquid::Tag - - #====================================== - # initialize - #====================================== - def initialize(tag_name, key, tokens) - super - @key = key.strip - end - - - - #====================================== - # render - #====================================== - def render(context) - if "#{context[@key]}" != "" # Check for page variable - key = "#{context[@key]}" - else - key = @key - end - - key = Liquid::Template.parse(key).render(context) # Parses and renders some Liquid syntax on arguments (allows expansions) - - site = context.registers[:site] # Jekyll site object - - lang = site.config['lang'] - - unless site.parsed_translations.has_key?(lang) - puts "Loading translation from file #{site.source}/_i18n/#{lang}.yml" - site.parsed_translations[lang] = YAML.load_file("#{site.source}/_i18n/#{lang}.yml") - end - - translation = site.parsed_translations[lang].access(key) if key.is_a?(String) - - if translation.nil? or translation.empty? - translation = site.parsed_translations[site.config['default_lang']].access(key) - - puts "Missing i18n key: #{lang}:#{key}" - puts "Using translation '%s' from default language: %s" %[translation, site.config['default_lang']] - end - - translation - end - end - - - - ############################################################################## - # class LocalizeInclude - # - # Localization by including whole files that contain the localization text. - # User must use the "tf" or "translate_file" liquid tags. - ############################################################################## - module Tags - class LocalizeInclude < IncludeTag - - #====================================== - # render - #====================================== - def render(context) - if "#{context[@file]}" != "" # Check for page variable - file = "#{context[@file]}" - else - file = @file - end - - file = Liquid::Template.parse(file).render(context) # Parses and renders some Liquid syntax on arguments (allows expansions) - - site = context.registers[:site] # Jekyll site object - - includes_dir = File.join(site.source, '_i18n/' + site.config['lang']) - - validate_file_name(file) - - Dir.chdir(includes_dir) do - choices = Dir['**/*'].reject { |x| File.symlink?(x) } - - if choices.include?( file) - source = File.read(file) - partial = Liquid::Template.parse(source) - - context.stack do - context['include'] = parse_params( context) if @params - contents = partial.render(context) - ext = File.extname(file) - - converter = site.converters.find { |c| c.matches(ext) } - contents = converter.convert(contents) unless converter.nil? - - contents - end - else - raise IOError.new "Included file '#{file}' not found in #{includes_dir} directory" - end - - end - end - end - end - - - - ############################################################################## - # class LocalizeLink - # - # Creates links or permalinks for translated pages. - # User must use the "tl" or "translate_link" liquid tags. - ############################################################################## - class LocalizeLink < Liquid::Tag - - #====================================== - # initialize - #====================================== - def initialize(tag_name, key, tokens) - super - @key = key - end - - - - #====================================== - # render - #====================================== - def render(context) - if "#{context[@key]}" != "" # Check for page variable - key = "#{context[@key]}" - else - key = @key - end - - key = Liquid::Template.parse(key).render(context) # Parses and renders some Liquid syntax on arguments (allows expansions) - - site = context.registers[:site] # Jekyll site object - - key = key.split - namespace = key[0] - lang = key[1] || site.config[ 'lang'] - default_lang = site.config['default_lang'] - baseurl = site.baseurl - pages = site.pages - url = ""; - - if default_lang != lang - baseurl = baseurl + "/" + lang - end - - for p in pages - unless p['namespace'].nil? - page_namespace = p['namespace'] - - if namespace == page_namespace - permalink = p['permalink_'+lang] || p['permalink'] - url = baseurl + permalink - end - end - end - - url - end - end - - -end # End module Jekyll - - - -################################################################################ -# class Hash -################################################################################ -unless Hash.method_defined? :access - class Hash - - #====================================== - # access - #====================================== - def access(path) - ret = self - - path.split('.').each do |p| - - if p.to_i.to_s == p - ret = ret[p.to_i] - else - ret = ret[p.to_s] || ret[p.to_sym] - end - - break unless ret - end - - ret - end - end end - - - -################################################################################ -# Liquid tags definitions - -Liquid::Template.register_tag('t', Jekyll::LocalizeTag ) -Liquid::Template.register_tag('translate', Jekyll::LocalizeTag ) -Liquid::Template.register_tag('tf', Jekyll::Tags::LocalizeInclude) -Liquid::Template.register_tag('translate_file', Jekyll::Tags::LocalizeInclude) -Liquid::Template.register_tag('tl', Jekyll::LocalizeLink ) -Liquid::Template.register_tag('translate_link', Jekyll::LocalizeLink ) - diff --git a/lib/overwrite_jekyll/document.rb b/lib/overwrite_jekyll/document.rb new file mode 100644 index 0000000..fe9330b --- /dev/null +++ b/lib/overwrite_jekyll/document.rb @@ -0,0 +1,26 @@ +module Jekyll + class Document + + if Gem::Version.new(Jekyll::VERSION) >= Gem::Version.new("3.0.0") + alias :populate_categories_org :populate_categories + + #====================================== + # populate_categories + # + # Monkey patched this method to remove unwanted strings + # ("_i18n" and language code) that are prepended to posts categories + # because of how the multilingual posts are arranged in subfolders. + #====================================== + def populate_categories + data['categories'].delete("_i18n") + data['categories'].delete(site.config['lang']) + + merge_data!({ + 'categories' => ( + Array(data['categories']) + Utils.pluralized_array_from_hash(data, 'category', 'categories') + ).map(&:to_s).flatten.uniq + }) + end + end + end +end diff --git a/lib/overwrite_jekyll/hash_custom.rb b/lib/overwrite_jekyll/hash_custom.rb new file mode 100644 index 0000000..da3b29a --- /dev/null +++ b/lib/overwrite_jekyll/hash_custom.rb @@ -0,0 +1,21 @@ +unless Hash.method_defined? :access + class Hash + + def access(path) + ret = self + + path.split('.').each do |p| + + if p.to_i.to_s == p + ret = ret[p.to_i] + else + ret = ret[p.to_s] || ret[p.to_sym] + end + + break unless ret + end + + ret + end + end +end diff --git a/lib/overwrite_jekyll/page.rb b/lib/overwrite_jekyll/page.rb new file mode 100644 index 0000000..ee36497 --- /dev/null +++ b/lib/overwrite_jekyll/page.rb @@ -0,0 +1,16 @@ +module Jekyll + class Page + + def permalink + return nil if data.nil? || data['permalink'].nil? + + if site.config['relative_permalinks'] + File.join(@dir, data['permalink']) + else + # Look if there's a permalink overwrite specified for this lang + data['permalink_'+site.config['lang']] || data['permalink'] + end + + end + end +end diff --git a/lib/overwrite_jekyll/post.rb b/lib/overwrite_jekyll/post.rb new file mode 100644 index 0000000..e347096 --- /dev/null +++ b/lib/overwrite_jekyll/post.rb @@ -0,0 +1,29 @@ +module Jekyll + + class Post + + if Gem::Version.new(Jekyll::VERSION) < Gem::Version.new("3.0.0") + alias :populate_categories_org :populate_categories + + #====================================== + # populate_categories + # + # Monkey patched this method to remove unwanted strings + # ("_i18n" and language code) that are prepended to posts categories + # because of how the multilingual posts are arranged in subfolders. + #====================================== + def populate_categories + categories_from_data = Utils.pluralized_array_from_hash(data, 'category', 'categories') + self.categories = ( + Array(categories) + categories_from_data + ).map {|c| c.to_s.downcase}.flatten.uniq + + self.categories.delete("_i18n") + self.categories.delete(site.config['lang']) + + return self.categories + end + end + end + +end diff --git a/lib/overwrite_jekyll/post_reader.rb b/lib/overwrite_jekyll/post_reader.rb new file mode 100644 index 0000000..5ee5ef3 --- /dev/null +++ b/lib/overwrite_jekyll/post_reader.rb @@ -0,0 +1,19 @@ +module Jekyll + class PostReader + + if Gem::Version.new(Jekyll::VERSION) >= Gem::Version.new("3.0.0") + alias :read_posts_org :read_posts + + def read_posts(dir) + translate_posts = !site.config['exclude_from_localizations'].include?("_posts") + if dir == '' && translate_posts + read_posts("_i18n/#{site.config['lang']}/") + else + read_posts_org(dir) + end + end + end + + end + +end diff --git a/lib/overwrite_jekyll/site.rb b/lib/overwrite_jekyll/site.rb new file mode 100644 index 0000000..77b4a8f --- /dev/null +++ b/lib/overwrite_jekyll/site.rb @@ -0,0 +1,100 @@ +module Jekyll + + + class Site + + attr_accessor :parsed_translations # Hash that stores parsed translations read from YAML files. + + alias :process_org :process + + #====================================== + # process + # + # Reads Jekyll and plugin configuration parameters set on _config.yml, sets + # main parameters and processes the website for each language. + #====================================== + def process + # Check if plugin settings are set, if not, set a default or quit. + #------------------------------------------------------------------------- + self.parsed_translations ||= {} + + self.config['exclude_from_localizations'] ||= [] + + if ( !self.config['languages'] or + self.config['languages'].empty? or + !self.config['languages'].all? + ) + puts 'You must provide at least one language using the "languages" setting on your _config.yml.' + + exit + end + + + # Variables + #------------------------------------------------------------------------- + + # Original Jekyll configurations + baseurl_org = self.config[ 'baseurl' ] # Baseurl set on _config.yml + dest_org = self.dest # Destination folder where the website is generated + + # Site building only variables + languages = self.config['languages'] # List of languages set on _config.yml + + # Site wide plugin configurations + self.config['default_lang'] = languages.first # Default language (first language of array set on _config.yml) + self.config[ 'lang'] = languages.first # Current language being processed + self.config['baseurl_root'] = baseurl_org # Baseurl of website root (without the appended language code) + self.config['translations'] = self.parsed_translations # Hash that stores parsed translations read from YAML files. Exposes this hash to Liquid. + + + # Build the website for default language + #------------------------------------------------------------------------- + puts "Building site for default language: \"#{self.config['lang']}\" to: #{self.dest}" + + process_org + + + # Build the website for the other languages + #------------------------------------------------------------------------- + + # Remove .htaccess file from included files, so it wont show up on translations folders. + self.include -= [".htaccess"] + + languages.drop(1).each do |lang| + + # Language specific config/variables + @dest = dest_org + "/" + lang + self.config['baseurl'] = baseurl_org + "/" + lang + self.config['lang'] = lang + + puts "Building site for language: \"#{self.config['lang']}\" to: #{self.dest}" + + process_org + end + + # Revert to initial Jekyll configurations (necessary for regeneration) + self.config[ 'baseurl' ] = baseurl_org # Baseurl set on _config.yml + @dest = dest_org # Destination folder where the website is generated + + puts 'Build complete' + end + + + # Support for old jekyll + if Gem::Version.new(Jekyll::VERSION) < Gem::Version.new("3.0.0") + alias :read_posts_org :read_posts + + def read_posts(dir) + translate_posts = !self.config['exclude_from_localizations'].include?("_posts") + + if dir == '' && translate_posts + read_posts("_i18n/#{self.config['lang']}/") + else + read_posts_org(dir) + end + + end + end + + end +end diff --git a/lib/plugin/version.rb b/lib/plugin/version.rb index 086d88b..e693ad4 100644 --- a/lib/plugin/version.rb +++ b/lib/plugin/version.rb @@ -1,6 +1,5 @@ module Jekyll module MultipleLanguagesPlugin - VERSION = "1.5.1" + VERSION = "1.5.3" end end - diff --git a/lib/tools/path_equivalent.rb b/lib/tools/path_equivalent.rb new file mode 100644 index 0000000..a9f7654 --- /dev/null +++ b/lib/tools/path_equivalent.rb @@ -0,0 +1,18 @@ +module Jekyll + module MultipleLanguagePluginTools + class PathEquivalent + def initialize exclude_path, static_path + @exclude_path = exclude_path + @static_path = static_path + end + + def check + # <=> Spaceship operator + # retun 0 if 2 operator are == + result = Pathname.new(@exclude_path) <=> @static_path + return true if result == 0 + false + end + end + end +end diff --git a/lib/tools/remover.rb b/lib/tools/remover.rb new file mode 100644 index 0000000..77cdda2 --- /dev/null +++ b/lib/tools/remover.rb @@ -0,0 +1,22 @@ +module Jekyll + module MultipleLanguagePluginTools + + class RemoverStaticFiles + def self.go static_file_relative_path, excluded_paths + excluded_paths.any? do |excluded_path| + same_path?(static_file_relative_path, excluded_path) + end + end + + private + + def self.same_path? static_file_relative_path, excluded_path + Pathname.new(static_file_relative_path).descend do |static_file_path| + path_equivalent_tool = PathEquivalent.new(excluded_path, static_file_path) + break(true) if path_equivalent_tool.check + end + end + end + + end +end diff --git a/test/base_test.rb b/test/base_test.rb new file mode 100644 index 0000000..330b457 --- /dev/null +++ b/test/base_test.rb @@ -0,0 +1,5 @@ +require 'minitest/autorun' +require 'minitest/pride' +require './lib/tools/path_equivalent' +require './lib/tools/remover' +require './test/tools_test' diff --git a/test/tools_test.rb b/test/tools_test.rb new file mode 100644 index 0000000..7b53741 --- /dev/null +++ b/test/tools_test.rb @@ -0,0 +1,20 @@ +module Jekyll + module MultipleLanguagePluginTools + class TestTools < Minitest::Test + + def test_delete_from_array + static_files = ['file.jpeg', 'file.txt', '/relative_path.pdf'].map{|value| Pathname.new(value)} + static_files.delete_if do |static_file| + RemoverStaticFiles.go static_file, ['file.jpeg'] + end + assert_equal static_files, ['file.txt', '/relative_path.pdf'].map{|value| Pathname.new(value)} + end + + def test_path_are_the_same + equivalent_tool = PathEquivalent.new('file.rb', Pathname.new('file.rb')) + assert equivalent_tool.check + end + + end + end +end