jekyll-polyglot 1.2.2 → 1.3.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: b617e95642f5c0337a8b7dd35416aad11a5dee21
4
- data.tar.gz: 83af2f5194ba33e22e9a8f77f7996af6f79fd07d
2
+ SHA256:
3
+ metadata.gz: 8d7425cddd591dc3592b0ff61562a3283e333b2239a56f27f1a031e3267f33b4
4
+ data.tar.gz: 6de2896cab126733b10f137b0a04e09bc73b1deb14e847b73012533f555fc2d2
5
5
  SHA512:
6
- metadata.gz: 7a3f519eb89584149730065114d513f06829964d7b0a01debf42599c586250a04a8b26352e4ab099a696bc5e66bc365abaf110ae9bb411f738181fcaee07409d
7
- data.tar.gz: 5844c839e5c9731782afd0323179c513d7c057d428e51d086b5bfda889ac0bf14fa2421bb3615075eabbb89d157eddfc95f4a6cc730ed443e339ce0b58d89903
6
+ metadata.gz: b91c4e63e27ca6e7d86d0dd2fe378e976abe8b1f3b5914f52399f5f6548b3187f9fdf96fc03c3ef142949428f88b5c5d772b62d01eb62dd36ae3f1aab704bd30
7
+ data.tar.gz: f54dfc40d3a06ecac353b0f5225532a917d49bb5a28aca75355472d463aa9fef510f79330f6f2bfca90f04d2af5b226e0f3fa3a8702747c8a2269c64f995161a
data/LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2015 - 2016 Samuel Volin
1
+ Copyright (c) 2015 - 2020 Samuel Volin
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4
4
 
data/README.md CHANGED
@@ -9,26 +9,38 @@ __Polyglot__ is a fast, painless, open-source internationalization plugin for [J
9
9
  Jekyll doesn't provide native support for multi-language blogs. This plugin was modeled after the [jekyll-multiple-languages-plugin](https://github.com/screeninteraction/jekyll-multiple-languages-plugin), whose implementation I liked, but execution I didn't.
10
10
 
11
11
  ## Installation
12
- `gem install jekyll-polyglot` and add jekyll-polyglot to your `_config.yml` like the following:
13
- ```yml
14
- gems:
12
+ Add jekyll-polyglot to your `Gemfile` if you are using Bundler:
13
+ ```Ruby
14
+ group :jekyll_plugins do
15
+ gem "jekyll-polyglot"
16
+ end
17
+ ```
18
+
19
+ Or install the gem manually by doing `gem install jekyll-polyglot` and specify the plugin using `_config.yml`:
20
+ ```YAML
21
+ plugins:
15
22
  - jekyll-polyglot
16
23
  ```
17
24
 
18
25
  ## Configuration
19
26
  In your `_config.yml` file, add the following preferences
20
- ```
27
+ ```YAML
21
28
  languages: ["en", "sv", "de", "fr"]
22
29
  default_lang: "en"
23
- exclude_from_localization: ["javascript", "images", "css"]
30
+ exclude_from_localization: ["javascript", "images", "css", "README.md"]
24
31
  parallel_localization: true
25
32
  ```
26
33
  These configuration preferences indicate
27
34
  - what i18n languages you wish to support
28
35
  - what is your default "fallback" language for your content
29
- - what root level folders are you excluding from localization
36
+ - what root level files/folders are excluded from localization, based
37
+ on if their paths start with any of the excluded regexp substrings
30
38
  - whether to run language processing in parallel or serial
31
39
 
40
+ The optional `lang_from_path: true` option enables getting page
41
+ language from the first or second path segment, e.g `de/first-one.md`, or
42
+ `_posts/zh_Hans_HK/use-second-segment.md` , if the lang frontmatter isn't defined.
43
+
32
44
  ## How To Use It
33
45
  When adding new posts and pages, add to the YAML front matter:
34
46
  ```
@@ -80,40 +92,86 @@ becomes
80
92
  <p>Nous sommes un restaurant situé à Paris . <a href="/fr/menu/">Ceci est notre menu.</a></p>
81
93
  </article>
82
94
  ```
83
- Voila!
95
+ Notice the link `<a href="/fr/menu/">...` directs to the french website.
84
96
 
85
97
  Even if you are falling back to `default_lang` page, relative links built on the *french* site will
86
98
  still link to *french* pages.
87
99
 
100
+ #### Relativized Absolute Urls
101
+ If you defined a site `url` in your `_config.yaml`, polyglot will automatically relativize absolute links pointing to your website directory:
102
+
103
+ ```md
104
+ ---
105
+ lang: fr
106
+ ---
107
+ Cliquez [ici]({{site.url}}) pour aller à l'entrée du site.
108
+ ```
109
+ becomes
110
+ ```html
111
+ <p>Cliquez <a href="https://mywebsite.com/fr/">ici</a> pour aller à l'entrée du site.
112
+ ```
113
+
114
+ #### Disabling Url Relativizing
115
+ If you don't want a url to be relativized, you can add a space explicitly into the href to prevents a url from being relativized by polyglot.
116
+
117
+ For example, the following urls will be relativized:
118
+
119
+ ```html
120
+ href="http://mywebsite.com/about"
121
+ href="/about"
122
+ ```
123
+
124
+ and the following urls will be left alone:
125
+
126
+ ```html
127
+ href=" http://mywebsite.com/about"
128
+ href=" /about"
129
+ ```
130
+
131
+ combine with a [html minifier](https://github.com/digitalsparky/jekyll-minifier) for a polished and production ready website.
132
+
133
+ #### Localized site.data
134
+
135
+ There are cases when `site.data` localization is required.
136
+ For instance: you might need to localize `_data/navigation.yml` that holds "navigation menu".
137
+ In order to localize it, just place language-specific files in `_data/:lang/...` folder, and Polyglot will bring those keys to the top level.
138
+
88
139
  ## How It Works
89
- This plugin makes modifications to existing Jekyll classes and modules, namely `Jekyll::StaticFile` and `Jekyll::Site`. These changes are as lightweight and slim as possible. The biggest change is in `Jekyll::Site.process`. Polyglot overwrites this method to instead spawn a seperate thread for each language you intend to process the site for. Each of those threads calls the original `Jekyll::Site.process` method with its language in mind, ensuring your website scales to support any number of languages, while building all of your site languages simultaneously.
140
+ This plugin makes modifications to existing Jekyll classes and modules, namely `Jekyll::StaticFile` and `Jekyll::Site`. These changes are as lightweight and slim as possible. The biggest change is in `Jekyll::Site.process`. Polyglot overwrites this method to instead spawn a separate thread for each language you intend to process the site for. Each of those threads calls the original `Jekyll::Site.process` method with its language in mind, ensuring your website scales to support any number of languages, while building all of your site languages simultaneously.
90
141
 
91
- `Jekyll::Site.process` is the entrypoint for the Jekyll build process. Take care whatever other plugins you use do not also attempt to overwrite this method. You may have problems.
142
+ `Jekyll::Site.process` is the entry point for the Jekyll build process. Take care whatever other plugins you use do not also attempt to overwrite this method. You may have problems.
92
143
 
93
144
  ## Features
94
145
  This plugin stands out from other I18n Jekyll plugins.
95
- - automatically corrects your relative links, keeping your *french* vistors on your *french* website, even when content has to fallback to the `default_lang`.
146
+ - automatically corrects your relative links, keeping your *french* visitors on your *french* website, even when content has to fallback to the `default_lang`.
96
147
  - builds all versions of your website *simultaneously*, allowing big websites to scale efficiently.
97
148
  - provides the liquid tag `{{ site.languages }}` to get an array of your I18n strings.
98
149
  - provides the liquid tag `{{ site.default_lang }}` to get the default_lang I18n string.
99
- - provides the liquid tag `{{ site.active_lang }}` to get the I18n language string the website was built for.
150
+ - provides the liquid tag `{{ site.active_lang }}` to get the I18n language string the website was built for. Alternative names for `active_lang` can be configured via `config.lang_vars`.
100
151
  - provides the liquid tag `{{ I18n_Headers https://yourwebsite.com/ }}` to append SEO bonuses to your website.
101
- - A creator that will answer all of your questions and issues.
152
+ - provides `site.data` localization for efficient rich text replacement.
153
+ - a creator that will answer all of your questions and issues.
102
154
 
103
155
  ## SEO Recipes
104
- Jekyll-polyglot has a few spectacular [Search Engine Optimization technique](https://untra.github.io/polyglot/seo) to ensure your jekyll blog gets the most out of it's multilingual audience. Check them out!
105
-
106
- ## Examples
107
- Check out the example project website [here](https://untra.github.io/polyglot)
108
- (Jekyll resources are on the project's [site](https://github.com/untra/polyglot/tree/site) branch)
156
+ Jekyll-polyglot has a few spectacular [Search Engine Optimization techniques](https://untra.github.io/polyglot/seo) to ensure your Jekyll blog gets the most out of it's multilingual audience. Check them out!
109
157
 
110
158
  ### Other Websites Built with Polyglot
111
-
159
+ let us know if you make a multilingual blog you want to share:
160
+ * [Polyglot project website](http://polyglot.untra.io)
112
161
  * [LogRhythm Corporate Website](http://logrhythm.com)
162
+ * [All Over Earth](https://allover.earth/)
163
+ * [Hanare Cafe in Toshijima, Japan](https://hanarecafe.com)
164
+ * [F-Droid](https://f-droid.org)
113
165
 
114
166
  ## Compatibility
115
- Currently supports Jekyll 3.0 .
116
- Windows users will need to disable parallel_localization on their machines by setting `parallel_localization: false` in the `_config.yml`
167
+ Currently supports Jekyll 3.0 , and Jekyll 4.0 (for the most part)
168
+
169
+ * *Windows users will need to disable parallel_localization on their machines by setting `parallel_localization: false` in the `_config.yml`
170
+ * In Jekyll 4.0 , SCSS source maps will generate improperly due to how Polyglot operates. The workaround is to disable the CSS sourcemaps. Adding rhe following to your `config.yml` will disable sourcemap generation:
171
+ ```yaml
172
+ sass:
173
+ sourcemap: never
174
+ ```
117
175
 
118
176
  ## Copyright
119
- Copyright (c) Samuel Volin 2015. License: MIT
177
+ Copyright (c) Samuel Volin 2020. License: MIT
@@ -1,6 +1,23 @@
1
1
  # hook to coordinate blog posts and pages into distinct urls,
2
2
  # and remove duplicate multilanguage posts and pages
3
3
  Jekyll::Hooks.register :site, :post_read do |site|
4
- site.posts.docs = site.coordinate_documents(site.posts.docs)
4
+ hook_coordinate(site)
5
+ end
6
+
7
+ def hook_coordinate(site)
8
+ # Copy the language specific data, by recursively merging it with the default data.
9
+ # Favour active_lang first, then default_lang, then any non-language-specific data.
10
+ # See: https://www.ruby-forum.com/topic/142809
11
+ merger = proc { |key, v1, v2| Hash === v1 && Hash === v2 ? v1.merge(v2, &merger) : v2 }
12
+ if site.data.include?(site.default_lang)
13
+ site.data = site.data.merge(site.data[site.default_lang], &merger)
14
+ end
15
+ if site.data.include?(site.active_lang)
16
+ site.data = site.data.merge(site.data[site.active_lang], &merger)
17
+ end
18
+
19
+ site.collections.each do |_, collection|
20
+ collection.docs = site.coordinate_documents(collection.docs)
21
+ end
5
22
  site.pages = site.coordinate_documents(site.pages)
6
23
  end
@@ -1,5 +1,11 @@
1
1
  # hook to make a call to process rendered documents,
2
2
  Jekyll::Hooks.register :site, :post_render do |site|
3
- site.process_documents(site.posts.docs)
3
+ hook_process(site)
4
+ end
5
+
6
+ def hook_process(site)
7
+ site.collections.each do |_, collection|
8
+ site.process_documents(collection.docs)
9
+ end
4
10
  site.process_documents(site.pages)
5
11
  end
@@ -12,13 +12,14 @@ module Jekyll
12
12
  def render(context)
13
13
  site = context.registers[:site]
14
14
  permalink = context.registers[:page]['permalink']
15
- i18n = "<meta http-equiv=\"Content-Language\" content=\"#{site.active_lang}\">"
16
- i18n += "<link rel=\"alternate\" i18n=\"#{site.default_lang}\""\
17
- " href=\"#{@url}#{permalink}\" />\n"
15
+ site_url = @url.empty? ? site.config['url'] : @url
16
+ i18n = "<meta http-equiv=\"Content-Language\" content=\"#{site.active_lang}\">\n"
17
+ i18n += "<link rel=\"alternate\" hreflang=\"#{site.default_lang}\" "\
18
+ "href=\" #{site_url}#{permalink}\"/>\n"
18
19
  site.languages.each do |lang|
19
20
  next if lang == site.default_lang
20
- i18n += "<link rel=\"alternate\" i18n=\"#{lang}\""\
21
- " href=\"#{@url}/#{lang}#{permalink}\" />\n"
21
+ i18n += "<link rel=\"alternate\" hreflang=\"#{lang}\" "\
22
+ "href=\"#{site_url}/#{lang}#{permalink}\"/>\n"
22
23
  end
23
24
  i18n
24
25
  end
@@ -1,41 +1,55 @@
1
1
  include Process
2
2
  module Jekyll
3
3
  class Site
4
- attr_reader :default_lang, :languages, :exclude_from_localization
4
+ attr_reader :default_lang, :languages, :exclude_from_localization, :lang_vars
5
5
  attr_accessor :file_langs, :active_lang
6
6
 
7
7
  def prepare
8
8
  @file_langs = {}
9
+ fetch_languages
10
+ @parallel_localization = config.fetch('parallel_localization', true)
11
+ @lang_from_path = config.fetch('lang_from_path', false)
12
+ @exclude_from_localization = config.fetch('exclude_from_localization', []).map do |e|
13
+ if File.directory?(e) and e[-1] != '/'
14
+ e + '/'
15
+ else
16
+ e
17
+ end
18
+ end
19
+
20
+ end
21
+
22
+ def fetch_languages
9
23
  @default_lang = config.fetch('default_lang', 'en')
10
24
  @languages = config.fetch('languages', ['en'])
11
- @parallel_localization = config.fetch('parallel_localization', true)
12
- (@keep_files << @languages - [@default_lang]).flatten!
13
- @exclude_from_localization = config.fetch('exclude_from_localization', [])
25
+ @keep_files += (@languages - [@default_lang])
14
26
  @active_lang = @default_lang
27
+ @lang_vars = config.fetch('lang_vars', [])
15
28
  end
16
29
 
17
30
  alias_method :process_orig, :process
18
31
  def process
19
32
  prepare
33
+ all_langs = (@languages + [@default_lang]).uniq
20
34
  if @parallel_localization
21
35
  pids = {}
22
- @languages.each do |lang|
36
+ all_langs.each do |lang|
23
37
  pids[lang] = fork do
24
38
  process_language lang
25
39
  end
26
40
  end
27
41
  Signal.trap('INT') do
28
- @languages.each do |lang|
42
+ all_langs.each do |lang|
29
43
  puts "Killing #{pids[lang]} : #{lang}"
30
44
  kill('INT', pids[lang])
31
45
  end
32
46
  end
33
- @languages.each do |lang|
47
+ all_langs.each do |lang|
34
48
  waitpid pids[lang]
35
49
  detach pids[lang]
36
50
  end
37
51
  else
38
- @languages.each do |lang|
52
+ all_langs.each do |lang|
39
53
  process_language lang
40
54
  end
41
55
  end
@@ -47,14 +61,28 @@ module Jekyll
47
61
  payload['site']['default_lang'] = default_lang
48
62
  payload['site']['languages'] = languages
49
63
  payload['site']['active_lang'] = active_lang
64
+ lang_vars.each do |v|
65
+ payload['site'][v] = active_lang
66
+ end
50
67
  payload
51
68
  end
52
69
 
53
70
  def process_language(lang)
54
71
  @active_lang = lang
55
72
  config['active_lang'] = @active_lang
56
- return process_orig if @active_lang == @default_lang
57
- process_active_language
73
+ lang_vars.each do |v|
74
+ config[v] = @active_lang
75
+ end
76
+ if @active_lang == @default_lang
77
+ then process_default_language
78
+ else process_active_language
79
+ end
80
+ end
81
+
82
+ def process_default_language
83
+ old_include = @include
84
+ process_orig
85
+ @include = old_include
58
86
  end
59
87
 
60
88
  def process_active_language
@@ -68,13 +96,32 @@ module Jekyll
68
96
  @exclude = old_exclude
69
97
  end
70
98
 
99
+ def derive_lang_from_path(doc)
100
+ if !@lang_from_path
101
+ return nil
102
+ end
103
+ segments = doc.relative_path.split('/')
104
+ if doc.relative_path[0] == '_' \
105
+ and segments.length > 2 \
106
+ and segments[1] =~ /^[a-z]{2,3}(:?[_-](:?[A-Za-z]{2}){1,2}){0,2}$/
107
+ return segments[1]
108
+ elsif segments.length > 1 \
109
+ and segments[0] =~ /^[a-z]{2,3}(:?[_-](:?[A-Za-z]{2}){1,2}){0,2}$/
110
+ return segments[0]
111
+ else
112
+ return nil
113
+ end
114
+ end
115
+
71
116
  # assigns natural permalinks to documents and prioritizes documents with
72
- # active_lang languages over others
117
+ # active_lang languages over others. If lang is not set in front matter,
118
+ # then this tries to derive from the path, if the lang_from_path is set.
119
+ # otherwise it will assign the document to the default_lang
73
120
  def coordinate_documents(docs)
74
121
  regex = document_url_regex
75
122
  approved = {}
76
123
  docs.each do |doc|
77
- lang = doc.data['lang'] || @default_lang
124
+ lang = doc.data['lang'] || derive_lang_from_path(doc) || @default_lang
78
125
  url = doc.url.gsub(regex, '/')
79
126
  doc.data['permalink'] = url
80
127
  next if @file_langs[url] == @active_lang
@@ -87,8 +134,15 @@ module Jekyll
87
134
 
88
135
  # performs any necesarry operations on the documents before rendering them
89
136
  def process_documents(docs)
137
+ return if @active_lang == @default_lang
138
+ url = config.fetch('url', false)
139
+ rel_regex = relative_url_regex
140
+ abs_regex = absolute_url_regex(url)
90
141
  docs.each do |doc|
91
- relativize_urls doc
142
+ relativize_urls(doc, rel_regex)
143
+ if url
144
+ then relativize_absolute_urls(doc, abs_regex, url)
145
+ end
92
146
  end
93
147
  end
94
148
 
@@ -106,18 +160,40 @@ module Jekyll
106
160
 
107
161
  # a regex that matches relative urls in a html document
108
162
  # matches href="baseurl/foo/bar-baz" and others like it
109
- # avoids matching excluded files
163
+ # avoids matching excluded files. prepare makes sure
164
+ # that all @exclude dirs have a trailing slash.
110
165
  def relative_url_regex
111
166
  regex = ''
112
- @exclude.each do |x|
167
+ (@exclude).each do |x|
168
+ regex += "(?!#{x})"
169
+ end
170
+ (@languages).each do |x|
113
171
  regex += "(?!#{x}\/)"
114
172
  end
115
- %r{href=\"#{@baseurl}\/((?:#{regex}[^,'\"\s\/?\.#]+\.?)*(?:\/[^\]\[\)\(\"\'\s]*)?)\"}
173
+ %r{href=\"?#{@baseurl}\/((?:#{regex}[^,'\"\s\/?\.#]+\.?)*(?:\/[^\]\[\)\(\"\'\s]*)?)\"}
116
174
  end
117
175
 
118
- def relativize_urls(doc)
119
- return if @active_lang == @default_lang
120
- doc.output.gsub!(relative_url_regex, "href=\"#{@baseurl}/#{@active_lang}/" + '\1"')
176
+ def absolute_url_regex(url)
177
+ regex = ''
178
+ (@exclude).each do |x|
179
+ regex += "(?!#{x})"
180
+ end
181
+ (@languages).each do |x|
182
+ regex += "(?!#{x}\/)"
183
+ end
184
+ %r{href=\"?#{url}#{@baseurl}\/((?:#{regex}[^,'\"\s\/?\.#]+\.?)*(?:\/[^\]\[\)\(\"\'\s]*)?)\"}
185
+ end
186
+
187
+ def relativize_urls(doc, regex)
188
+ return if doc.output.nil?
189
+
190
+ doc.output.gsub!(regex, "href=\"#{@baseurl}/#{@active_lang}/" + '\1"')
191
+ end
192
+
193
+ def relativize_absolute_urls(doc, regex, url)
194
+ return if doc.output.nil?
195
+
196
+ doc.output.gsub!(regex, "href=\"#{url}#{@baseurl}/#{@active_lang}/" + '\1"')
121
197
  end
122
198
  end
123
199
  end
@@ -1,5 +1,5 @@
1
1
  module Jekyll
2
2
  module Polyglot
3
- VERSION="1.2.2"
3
+ VERSION = '1.3.3'.freeze
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,35 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jekyll-polyglot
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.2
4
+ version: 1.3.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Samuel Volin
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-07-22 00:00:00.000000000 Z
11
+ date: 2020-04-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: jekyll
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - '>='
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
19
  version: '3.0'
20
- - - ~>
21
- - !ruby/object:Gem::Version
22
- version: '3.1'
23
20
  type: :runtime
24
21
  prerelease: false
25
22
  version_requirements: !ruby/object:Gem::Requirement
26
23
  requirements:
27
- - - '>='
24
+ - - ">="
28
25
  - !ruby/object:Gem::Version
29
26
  version: '3.0'
30
- - - ~>
31
- - !ruby/object:Gem::Version
32
- version: '3.1'
33
27
  description: Fast open source i18n plugin for Jekyll blogs.
34
28
  email: untra.sam@gmail.com
35
29
  executables: []
@@ -60,17 +54,16 @@ require_paths:
60
54
  - lib
61
55
  required_ruby_version: !ruby/object:Gem::Requirement
62
56
  requirements:
63
- - - '>='
57
+ - - ">="
64
58
  - !ruby/object:Gem::Version
65
59
  version: '0'
66
60
  required_rubygems_version: !ruby/object:Gem::Requirement
67
61
  requirements:
68
- - - '>='
62
+ - - ">="
69
63
  - !ruby/object:Gem::Version
70
64
  version: '0'
71
65
  requirements: []
72
- rubyforge_project:
73
- rubygems_version: 2.6.6
66
+ rubygems_version: 3.1.2
74
67
  signing_key:
75
68
  specification_version: 4
76
69
  summary: I18n plugin for Jekyll Blogs