jekyll-polyglot 1.9.0 → 1.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 58fab59c4c6aabba378edb4622f960b9ee2910c41e9b7cb329218cf4602bfaa2
4
- data.tar.gz: 2a077894396baca9c8215a44abe6734abd9c1c00d0975259cf98380f77e72a10
3
+ metadata.gz: '0459aa05cc1025bea0ca2aef71ad7e3e4a0c33726b1f32e4d5f2e19d521a06aa'
4
+ data.tar.gz: 245aa4b72aa80fac516b0cc9b04c396ef0ec55366aadefbb73ba8fa9ca47df93
5
5
  SHA512:
6
- metadata.gz: 1c90c5e30bd2703cfab18b75b0a23d6a94350709dcd4d1acfade18497f4ce7bdddeba18cc9efd1cf527e3aeb5295e422e0108da10a12f556b2a007f5e57a26b6
7
- data.tar.gz: fdda50a81bbbd06e90e4b170be83f207b01f1f66eeabea7b4aff68421bc5bbcdf124e3cccf737d01cfa59f48fb914121953140cdde9ecadd6f572b31c1ba08d7
6
+ metadata.gz: d8f4162ee486ebf72f6c5be6714bb5aed0a60f5ca0798480efbc8a68f84cd94c40b9db9efbb6160317ca974f600cbe82ac82c0934a833d162135b873a3b000da
7
+ data.tar.gz: c5367a20ee1ea4983e5cc8485204f11da88d4a3914ccfc5aa62d76d78cd364fd15c223e99a4bbec5f27d306c7be4226232faa3c17b38951dd9102ead2e5e02c7
data/README.md CHANGED
@@ -1,7 +1,8 @@
1
1
  🔤 Polyglot
2
2
  ---
3
3
  [![Gem Version](https://badge.fury.io/rb/jekyll-polyglot.svg)](https://badge.fury.io/rb/jekyll-polyglot)
4
- [![CircleCI](https://circleci.com/gh/untra/polyglot/tree/master.svg?style=svg)](https://circleci.com/gh/untra/polyglot/?branch=master)
4
+ [![CircleCI](https://circleci.com/gh/untra/polyglot/tree/main.svg?style=svg)](https://circleci.com/gh/untra/polyglot/?branch=main)
5
+ [![codecov](https://codecov.io/gh/untra/polyglot/graph/badge.svg?token=AAIYBIxdWr)](https://codecov.io/gh/untra/polyglot)
5
6
 
6
7
  __Polyglot__ is a fast, painless, open-source internationalization plugin for [Jekyll](http://jekyllrb.com) blogs. Polyglot is easy to set up and use with any Jekyll project, and it scales to the languages you want to support. With fallback support for missing content, automatic url relativization, and powerful SEO tools, Polyglot allows any multi-language jekyll blog to focus on content without the cruft.
7
8
 
@@ -38,9 +39,7 @@ These configuration preferences indicate
38
39
  - whether to run language processing in parallel or serial. Set to `false` if building on Windows hosts, or if Polyglot collides with other Jekyll plugins.
39
40
  - your jekyll website production url. Make sure this value is set; Polyglot requires this to relative site urls correctly, and to make functioning language switchers.
40
41
 
41
- The optional `lang_from_path: true` option enables getting page
42
- language from the first or second path segment, e.g `de/first-one.md`, or
43
- `_posts/zh_Hans_HK/use-second-segment.md` , if the lang frontmatter isn't defined.
42
+ The optional `lang_from_path: true` option enables getting the page language from a filepath segment seperated by `/` or `.`, e.g `de/first-one.md`, or `_posts/zh_HK/use-second-segment.md` , if the lang frontmatter isn't defined.
44
43
 
45
44
  ## How To Use It
46
45
  When adding new posts and pages, add to the YAML front matter:
@@ -51,7 +50,7 @@ or whatever appropriate [I18n language code](https://developer.chrome.com/docs/e
51
50
  the page should build for. And you're done. Ideally, when designing your site, you should
52
51
  organize files by their relative urls.
53
52
 
54
- You can see how the live Polyglot website [configures and supports multiple languages](https://github.com/untra/polyglot/blob/master/site/_config.yml#L28-L37), and examples of [community](https://github.com/untra/polyglot/pull/155) [language](https://github.com/untra/polyglot/pull/167) [contributions](https://github.com/untra/polyglot/pull/177).
53
+ You can see how the live Polyglot website [configures and supports multiple languages](https://github.com/untra/polyglot/blob/main/site/_config.yml#L28-L37), and examples of [community](https://github.com/untra/polyglot/pull/155) [language](https://github.com/untra/polyglot/pull/167) [contributions](https://github.com/untra/polyglot/pull/177).
55
54
 
56
55
  Polyglot works by associating documents with similar permalinks to the `lang` specified in their frontmatter. Files that correspond to similar routes should have identical permalinks. If you don't provide a permalink for a post, ___make sure you are consistent___ with how you place and name corresponding files:
57
56
  ```
@@ -113,7 +112,7 @@ Estos somos nosotros!
113
112
  ```
114
113
 
115
114
  Additionally, if you are also using the `jekyll-redirect-from` plugin, pages coordinated this way will automatically have redirects created between pages.
116
- So `/es/about` will automatically redirect to `/es/acerca-de` and `/acerca-de` can redirect to `/about`. If you use this approach, be sure to also employ a customized [redirect.html](https://github.com/untra/polyglot/blob/master/site/_layouts/redirect.html).
115
+ So `/es/about` will automatically redirect to `/es/acerca-de` and `/acerca-de` can redirect to `/about`. If you use this approach, be sure to also employ a customized [redirect.html](https://github.com/untra/polyglot/blob/main/site/_layouts/redirect.html).
117
116
 
118
117
  #### Fallback Language Support
119
118
  Lets say you are building your website. You have an `/about/` page written in *english*, *german* and
@@ -161,7 +160,7 @@ becomes
161
160
 
162
161
  ### Disabling Url Relativizing
163
162
  _New in 1.4.0_
164
- If you dont want a href attribute to be relativized (such as for making [a language switcher](https://github.com/untra/polyglot/blob/master/site/_includes/sidebar.html#L40)), you can use the block tag:
163
+ If you dont want a href attribute to be relativized (such as for making [a language switcher](https://github.com/untra/polyglot/blob/main/site/_includes/sidebar.html#L40)), you can use the block tag:
165
164
 
166
165
  ```html
167
166
  {% static_href %}href="..."{% endstatic_href %}
@@ -252,7 +251,7 @@ Polyglot will only start builds after it confirms there is a cpu core ready to a
252
251
  ### Writing Tests and Debugging
253
252
  _:wave: I need assistance with modern ruby best practices for test maintenance with rake and rspec. If you got the advice I have the ears._
254
253
 
255
- Tests are run with `bundle exec rake`. Tests are in the `/spec` directory, and test failure output detail can be examined in the `rspec.xml` file.
254
+ Tests are run with `test.sh`. Tests are in the `/spec` directory, and test failure output detail can be examined in the `rspec.json` file. Code Coverage details are in the the `coverage` directory.
256
255
 
257
256
  ## Features
258
257
  This plugin stands out from other I18n Jekyll plugins.
@@ -8,7 +8,7 @@ def hook_coordinate(site)
8
8
  # Copy the language specific data, by recursively merging it with the default data.
9
9
  # Favour active_lang first, then default_lang, then any non-language-specific data.
10
10
  # See: https://www.ruby-forum.com/topic/142809
11
- merger = proc { |key, v1, v2| Hash === v1 && Hash === v2 ? v1.merge(v2, &merger) : v2 }
11
+ merger = proc { |_key, v1, v2| v1.is_a?(Hash) && v2.is_a?(Hash) ? v1.merge(v2, &merger) : v2 }
12
12
  if site.data.include?(site.default_lang)
13
13
  site.data = site.data.merge(site.data[site.default_lang], &merger)
14
14
  end
@@ -16,7 +16,7 @@ def hook_coordinate(site)
16
16
  site.data = site.data.merge(site.data[site.active_lang], &merger)
17
17
  end
18
18
 
19
- site.collections.each do |_, collection|
19
+ site.collections.each_value do |collection|
20
20
  collection.docs = site.coordinate_documents(collection.docs)
21
21
  end
22
22
  site.pages = site.coordinate_documents(site.pages)
@@ -4,7 +4,7 @@ Jekyll::Hooks.register :site, :post_render do |site|
4
4
  end
5
5
 
6
6
  def hook_process(site)
7
- site.collections.each do |_, collection|
7
+ site.collections.each_value do |collection|
8
8
  site.process_documents(collection.docs)
9
9
  end
10
10
  site.process_documents(site.pages)
@@ -11,18 +11,40 @@ module Jekyll
11
11
 
12
12
  def render(context)
13
13
  site = context.registers[:site]
14
- permalink = context.registers[:page]['permalink']
15
- permalink_lang = context.registers[:page]['permalink_lang']
16
- site_url = @url.empty? ? site.config['url'] : @url
14
+ page = context.registers[:page]
15
+ permalink = page['permalink'] || page['url'] || ''
16
+ permalink = "/#{permalink}" unless permalink.start_with?("/")
17
+ page_id = page['page_id']
18
+ permalink_lang = page['permalink_lang']
19
+ baseurl = site.config['baseurl'] || ''
20
+ site_url = @url.empty? ? site.config['url'] + baseurl : @url
17
21
  i18n = "<meta http-equiv=\"Content-Language\" content=\"#{site.active_lang}\">\n"
18
- i18n += "<link rel=\"alternate\" hreflang=\"#{site.default_lang}\" "\
19
- "href=\"#{site_url}/#{permalink}\"/>\n"
20
- site.languages.each do |lang|
21
- next if lang == site.default_lang
22
22
 
23
- url = permalink_lang && permalink_lang[lang] ? permalink_lang[lang] : permalink
24
- i18n += "<link rel=\"alternate\" hreflang=\"#{lang}\" "\
25
- "href=\"#{site_url}/#{lang}/#{url}\"/>\n"
23
+ # Find all documents with the same page_id
24
+ docs_with_same_id = site.collections.values
25
+ .flat_map(&:docs)
26
+ .filter { |doc| !doc.data['page_id'].nil? }
27
+ .select { |doc| doc.data['page_id'] == page_id }
28
+
29
+ # Build a hash of lang => permalink for all matching docs
30
+ lang_to_permalink = docs_with_same_id.to_h { |doc| [doc.data['lang'], doc.data['permalink']] }
31
+
32
+ # Canonical should always point to the current page's permalink (active_lang)
33
+ current_lang = site.active_lang
34
+ current_permalink = lang_to_permalink[current_lang] || (permalink_lang && permalink_lang[current_lang]) || permalink
35
+ current_permalink = "/#{current_permalink}" unless current_permalink.start_with?("/")
36
+ current_lang_prefix = current_lang == site.default_lang ? '' : "/#{current_lang}"
37
+ i18n += "<link rel=\"canonical\" href=\"#{site_url}#{current_lang_prefix}#{current_permalink}\"/>\n"
38
+
39
+ site.languages.each do |lang|
40
+ alt_permalink = lang_to_permalink[lang] || (permalink_lang && permalink_lang[lang]) || permalink
41
+ alt_permalink = "/#{alt_permalink}" unless alt_permalink.start_with?("/")
42
+ i18n += if lang == site.default_lang
43
+ "<link rel=\"alternate\" hreflang=\"#{lang}\" href=\"#{site_url}#{alt_permalink}\"/>\n" \
44
+ "<link rel=\"alternate\" hreflang=\"x-default\" href=\"#{site_url}#{alt_permalink}\"/>\n"
45
+ else
46
+ "<link rel=\"alternate\" hreflang=\"#{lang}\" href=\"#{site_url}/#{lang}#{alt_permalink}\"/>\n"
47
+ end
26
48
  end
27
49
  i18n
28
50
  end
@@ -1,21 +1,17 @@
1
1
  module Jekyll
2
2
  module Polyglot
3
3
  module Liquid
4
- class StaticHrefTag < :: Liquid::Block
5
- def initialize(tag_name, params, tokens)
6
- super
7
- end
8
-
4
+ class StaticHrefTag < ::Liquid::Block
9
5
  def render(context)
10
6
  text = super
11
- href_attrs = text.strip.split '='
7
+ href_attrs = text.strip.split('=', 2)
12
8
  valid = (href_attrs.length == 2 && href_attrs[0] == 'href') && href_attrs[1].start_with?('"') && href_attrs[1].end_with?('"')
13
9
  unless valid
14
- raise Liquid::SyntaxError, "static_href parameters must include match href=\"...\" attribute param, eg. href=\"http://example.com\, href=\"/about\", href=\"/\" , instead got:\n#{text}"
10
+ raise Liquid::SyntaxError, "static_href parameters must include match href=\"...\" attribute param, eg. href=\"http://example.com, href=\"/about\", href=\"/\" , instead got:\n#{text}"
15
11
  end
16
12
 
17
13
  href_value = href_attrs[1]
18
- # href writes out as ferh="..." explicitly wrong, to be cauaght by seperate processor for nonrelativized links
14
+ # href writes out as ferh="..." explicitly wrong, to be caught by separate processor for nonrelativized links
19
15
  "ferh=#{href_value}"
20
16
  end
21
17
  end
@@ -1,3 +1,4 @@
1
+ require 'English'
1
2
  require 'etc'
2
3
 
3
4
  include Process
@@ -31,7 +32,7 @@ module Jekyll
31
32
  alias process_orig process
32
33
  def process
33
34
  prepare
34
- all_langs = (@languages + [@default_lang]).uniq
35
+ all_langs = ([@default_lang] + @languages).uniq
35
36
  if @parallel_localization
36
37
  nproc = Etc.nprocessors
37
38
  pids = {}
@@ -42,11 +43,11 @@ module Jekyll
42
43
  end
43
44
  while pids.length >= (lang == all_langs[-1] ? 1 : nproc)
44
45
  sleep 0.1
45
- pids.map do |lang, pid|
46
+ pids.map do |pid_lang, pid|
46
47
  next unless waitpid pid, Process::WNOHANG
47
48
 
48
- pids.delete lang
49
- raise "Polyglot subprocess #{pid} (#{lang}) failed (#{$?.exitstatus})" unless $?.success?
49
+ pids.delete pid_lang
50
+ raise "Polyglot subprocess #{pid} (#{lang}) failed (#{$CHILD_STATUS.exitstatus})" unless $CHILD_STATUS.success?
50
51
  end
51
52
  end
52
53
  end
@@ -127,13 +128,6 @@ module Jekyll
127
128
  end
128
129
  end
129
130
 
130
- # loop through all segments and check if they match the language regex
131
- segments.each do |segment|
132
- if @languages.include?(segment)
133
- return segment
134
- end
135
- end
136
-
137
131
  nil
138
132
  end
139
133
 
@@ -163,21 +157,28 @@ module Jekyll
163
157
  approved[page_id] = doc
164
158
  @file_langs[page_id] = lang
165
159
  end
166
- approved.values.each { |doc| assignPageRedirects(doc, docs) }
167
- approved.values.each { |doc| assignPageLanguagePermalinks(doc, docs) }
160
+ approved.each_value do |doc|
161
+ assignPageRedirects(doc, docs)
162
+ assignPageLanguagePermalinks(doc, docs)
163
+ end
168
164
  approved.values
169
165
  end
170
166
 
171
167
  def assignPageRedirects(doc, docs)
172
168
  pageId = doc.data['page_id']
173
169
  if !pageId.nil? && !pageId.empty?
174
- lang = doc.data['lang'] || derive_lang_from_path(doc) || @default_lang
175
- langPrefix = lang === @default_lang ? '' : "#{lang}/"
176
- redirectDocs = docs.select do |dd|
177
- doclang = dd.data['lang'] || derive_lang_from_path(dd) || @default_lang
178
- dd.data['page_id'] == pageId && doclang != lang && dd.data['permalink'] != doc.data['permalink']
170
+ redirects = []
171
+
172
+ docs_with_same_id = docs.select { |dd| dd.data['page_id'] == pageId }
173
+
174
+ # For each document with the same page_id
175
+ docs_with_same_id.each do |dd|
176
+ # Add redirect if it's a different permalink
177
+ if dd.data['permalink'] != doc.data['permalink']
178
+ redirects << dd.data['permalink']
179
+ end
179
180
  end
180
- redirects = redirectDocs.map { |dd| dd.data['permalink'] }
181
+
181
182
  doc.data['redirect_from'] = redirects
182
183
  end
183
184
  end
@@ -221,7 +222,7 @@ module Jekyll
221
222
  def document_url_regex
222
223
  regex = ''
223
224
  (@languages || []).each do |lang|
224
- regex += "([\/\.]#{lang}[\/\.])|"
225
+ regex += "([/.]#{lang}[/.])|"
225
226
  end
226
227
  regex.chomp! '|'
227
228
  /#{regex}/
@@ -238,7 +239,7 @@ module Jekyll
238
239
  regex += "(?!#{x})"
239
240
  end
240
241
  @languages.each do |x|
241
- regex += "(?!#{x}\/)"
242
+ regex += "(?!#{x}/)"
242
243
  end
243
244
  end
244
245
  start = disabled ? 'ferh' : 'href'
@@ -256,18 +257,19 @@ module Jekyll
256
257
  regex += "(?!#{x})"
257
258
  end
258
259
  @languages.each do |x|
259
- regex += "(?!#{x}\/)"
260
+ regex += "(?!#{x}/)"
260
261
  end
261
262
  end
262
263
  start = disabled ? 'ferh' : 'href'
263
- %r{(?<!hreflang="#{@default_lang}" )#{start}="?#{url}#{@baseurl}/((?:#{regex}[^,'"\s/?.]+\.?)*(?:/[^\]\[)("'\s]*)?)"}
264
+ neglookbehind = disabled ? "" : "(?<!hreflang=\"#{@default_lang}\" |rel=\"canonical\" )"
265
+ %r{#{neglookbehind}#{start}="?#{url}#{@baseurl}/((?:#{regex}[^,'"\s/?.]+\.?)*(?:/[^\]\[)("'\s]*)?)"}
264
266
  end
265
267
 
266
268
  def relativize_urls(doc, regex)
267
269
  return if doc.output.nil?
268
270
 
269
271
  modified_output = doc.output.dup
270
- modified_output.gsub!(regex, "href=\"#{@baseurl}/#{@active_lang}/" + '\1"')
272
+ modified_output.gsub!(regex, "href=\"#{@baseurl}/#{@active_lang}/\\1\"")
271
273
  doc.output = modified_output
272
274
  end
273
275
 
@@ -275,7 +277,7 @@ module Jekyll
275
277
  return if doc.output.nil?
276
278
 
277
279
  modified_output = doc.output.dup
278
- modified_output.gsub!(regex, "href=\"#{url}#{@baseurl}/#{@active_lang}/" + '\1"')
280
+ modified_output.gsub!(regex, "href=\"#{url}#{@baseurl}/#{@active_lang}/\\1\"")
279
281
  doc.output = modified_output
280
282
  end
281
283
 
@@ -283,7 +285,7 @@ module Jekyll
283
285
  return if doc.output.nil?
284
286
 
285
287
  modified_output = doc.output.dup
286
- modified_output.gsub!(regex, "href=\"#{url}#{@baseurl}/" + '\1"')
288
+ modified_output.gsub!(regex, "href=\"#{url}#{@baseurl}/\\1\"")
287
289
  doc.output = modified_output
288
290
  end
289
291
 
@@ -291,7 +293,7 @@ module Jekyll
291
293
  return if doc.output.nil?
292
294
 
293
295
  modified_output = doc.output.dup
294
- modified_output.gsub!(regex, "href=\"#{@baseurl}/" + '\1"')
296
+ modified_output.gsub!(regex, "href=\"#{@baseurl}/\\1\"")
295
297
  doc.output = modified_output
296
298
  end
297
299
  end
@@ -1,19 +1,20 @@
1
-
2
1
  module Jekyll
3
2
  # Alteration to Jekyll StaticFile
4
3
  # provides aliased methods to direct write to skip files
5
4
  # excluded from localization
6
5
  class StaticFile
7
- alias_method :write_orig, :write
6
+ alias write_orig write
8
7
  def write(dest)
9
8
  return false if exclude_from_localization?
9
+
10
10
  write_orig(dest)
11
11
  end
12
12
 
13
13
  def exclude_from_localization?
14
14
  return false if @site.active_lang == @site.default_lang
15
+
15
16
  @site.exclude_from_localization.each do |e|
16
- return true if relative_path[1..-1].start_with?(e)
17
+ return true if relative_path[1..].start_with?(e)
17
18
  end
18
19
  false
19
20
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jekyll-polyglot
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.9.0
4
+ version: 1.10.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Samuel Volin
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-01-18 00:00:00.000000000 Z
11
+ date: 2025-07-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: jekyll
@@ -54,7 +54,8 @@ files:
54
54
  homepage: https://polyglot.untra.io/
55
55
  licenses:
56
56
  - MIT
57
- metadata: {}
57
+ metadata:
58
+ rubygems_mfa_required: 'true'
58
59
  post_install_message:
59
60
  rdoc_options: []
60
61
  require_paths:
@@ -63,12 +64,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
63
64
  requirements:
64
65
  - - ">="
65
66
  - !ruby/object:Gem::Version
66
- version: 2.7.0
67
+ version: 3.1.0
67
68
  required_rubygems_version: !ruby/object:Gem::Requirement
68
69
  requirements:
69
70
  - - ">="
70
71
  - !ruby/object:Gem::Version
71
- version: 2.7.0
72
+ version: 3.1.0
72
73
  requirements: []
73
74
  rubygems_version: 3.3.7
74
75
  signing_key: