jekyll-locale 0.1.0 → 0.2.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
  SHA1:
3
- metadata.gz: 73cdeebfabff92747661cda740330d4fadb99139
4
- data.tar.gz: 6bb5b58bdb7420b41ea12c5b2d3f5f6267e93623
3
+ metadata.gz: 95f578476bc1531c27696fd1218bc914ec176686
4
+ data.tar.gz: e3723615a5e94829370795bcc51a4d70c27b20db
5
5
  SHA512:
6
- metadata.gz: c1182409d6e2c03b9aec4a8af42fbe9ccffbc72b956df482931e47ee3d6ba534b5e9055025cb8201a3709f00cd849aa2886b22122789aff6f2b2af97a8d1fc35
7
- data.tar.gz: ba66142dc23a732e769a10085cdcf0135a4d33d485fe61d5f90788a5ab541cb2dab8491443865ab9e66a9179e1b19a3e0a55ebe65d335eb24a008a7073fdbff9
6
+ metadata.gz: 8cd1ed64b59d8f5f8f308abba21bc6d1cbf29ed54f79d317dcd6741d1b73c37ebed95a12e2349c0bf65e5d3531394fcefb83c6a0edde6c40dac85e606a93080b
7
+ data.tar.gz: d37d608b72baff43775909273f1ebe3cf73452d1dcac35baa7bf168174d379fccc8fa4cd4d5266260a654cbb14e9292acad2f854a440c1b320c43f661b96ed79
data/README.md CHANGED
@@ -1,3 +1,129 @@
1
1
  # Jekyll Locale
2
2
 
3
- A localization plugin for Jekyll
3
+ A localization plugin for Jekyll.
4
+
5
+
6
+ ## Features
7
+
8
+ * Exposes a `{{ locale }}` object for your Liquid templates. The *payload* for this object is derived from data files and
9
+ has been *preconfigured* with the following:
10
+
11
+ ```yaml
12
+ locale : en # Sets the 'default locale' for the site
13
+ locales_dir : locales # Sets the base location for translation data, within your configured `data_dir`.
14
+ # Therefore, this setting implies that the plugin looks for translation data in
15
+ # either `_data/locales/` or a data file named `locales`. e.g. `_data/locales.yml`.
16
+ ```
17
+ Ergo, `{{ locale }}` is simply a *syntactic sugar* for the construct `{{ site.data[site.locales_dir][site.locale] }}`.
18
+ * Generates a *copy* of every page that renders into a HTML file, and every document set to be written, and renders
19
+ them into dedicated urls prepended by a supported locale.
20
+ For example, if one were to configure the plugin with `available_locales: ["de", "fr", "en", "es"]`, then a file
21
+ named `about.md` with custom permalink set to `/about/` will result in the following files:
22
+ * `_site/about/index.html`
23
+ * `_site/de/about/index.html`
24
+ * `_site/es/about/index.html`
25
+ * `_site/fr/about/index.html`
26
+
27
+
28
+ ## Usage
29
+
30
+ 1. Add plugin to the `:jekyll_plugins` group in your Gemfile:
31
+
32
+ ```ruby
33
+ group :jekyll_plugins do
34
+ gem "jekyll-locale", "~> 0.1"
35
+ end
36
+ ```
37
+
38
+ 2. Decide what the default locale for your site is going to be, what other locales need to be rendered, and where you'd
39
+ place the translation data files. Then edit your config file to override the default plugin configuration, as required.
40
+ (See above section for default settings). For example, to render the site with data for just the custom `fr` locale:
41
+
42
+ ```yaml
43
+ # _config.yml
44
+
45
+ author: John Doe
46
+ locale: "fr"
47
+ ```
48
+
49
+ But if you'd like the site to be rendered using both the default `en` and custom `fr` locales, then
50
+
51
+ ```yaml
52
+ # _config.yml
53
+
54
+ author: John Doe
55
+ available_locales: ["fr"] # or ["fr", "en"] if you want
56
+ ```
57
+
58
+ 3. Prepare your locale data file(s) with appropriate key-value pairs. For example,
59
+
60
+ ```yaml
61
+ # _data/locales.yml
62
+
63
+ en:
64
+ home-page: Home
65
+ about me : About Me
66
+ portfolio: Portfolio
67
+ fr:
68
+ home-page: Accueil
69
+ about me : À propos
70
+ portfolio: Portefeuille
71
+ ```
72
+ *(Note the use of heterogeneous format of keys..)*
73
+
74
+ 4. Use the data above in a template or a document through the {{ locale }} object. For example,
75
+
76
+ ```
77
+ List of link names in my navbar:
78
+ * {{ locale.home_page }}
79
+ * {{ locale.about_me }}
80
+ * {{ locale.portfolio }}
81
+ ```
82
+ *(Note that the ids passed to the `locale` object contain an underscore instead.)*
83
+ The locale data keys are stored internally as `snake_case` strings. So `about me` or `about-me` will always be stored
84
+ as `about_me` internally and the corresponding value can only be retrieved by using the snake_cased key.
85
+
86
+ Additionally, every page can determine its own locale via the `{{ page.locale }} construct. For example,
87
+
88
+ ```html
89
+ <!DOCTYPE html>
90
+ <html lang="{{ page.locale }}">
91
+ ```
92
+
93
+
94
+ ## Advanced Usage
95
+
96
+ Each generated locale page is aware of its canonical page and its sibling locale page (for sites rendering three or more
97
+ locales) and can be used to render meta tags for optimal SEO.
98
+
99
+ Adding the following Liquid construct inside your `<head />` tag will render the markup that tells the crawler how the
100
+ pages are related to each other:
101
+
102
+ ```html
103
+ {% for item in page.hreflangs %}
104
+ <link rel="{{ item.relation }}" hreflang="{{ item.locale }}" href="{{ item.url | absolute_url }}" />
105
+ {% endfor %}
106
+ ```
107
+
108
+ For example, `about.md` page with `permalink: /about/` in a site setup to render for locales `["en", "es", "fr"]`
109
+ and hosted at `http://example.com` will render with the following:
110
+
111
+ ```html
112
+ <link rel="canonical" hreflang="en" href="http://example.com/about/" />
113
+ <link rel="alternate" hreflang="es" href="http://example.com/es/about/" />
114
+ <link rel="alternate" hreflang="fr" href="http://example.com/fr/about/" />
115
+ ```
116
+
117
+ *The above use of `rel="canonical"` with `hreflang` attribute is generally frowned upon and not recommended by Google.* </br>
118
+ Instead filter out the canonical url from the for-loop, and render the canonical link as an `alternate` with the
119
+ `x-default` tag, along with a self-referencing declaration:
120
+
121
+ ```html
122
+ <link rel="alternate" hreflang="{{ page.locale }}" href="{{ page.url | absolute_url }}" />
123
+ {% for item in page.hreflangs %}
124
+ {% unless item.relation == 'canonical' %}
125
+ <link rel="{{ item.relation }}" hreflang="{{ item.locale }}" href="{{ item.url | absolute_url }}" />
126
+ {% endunless %}
127
+ {% endfor %}
128
+ <link rel="alternate" hreflang="x-default" href="{{ page.url | absolute_url }}" />
129
+ ```
@@ -7,4 +7,10 @@ module Jekyll
7
7
  mutable false
8
8
  private def_delegator :@obj, :data, :fallback_data
9
9
  end
10
+
11
+ #
12
+
13
+ class Locale::PageDrop < Locale::Drop
14
+ def_delegators :@obj, :locale, :url
15
+ end
10
16
  end
@@ -2,29 +2,60 @@
2
2
 
3
3
  module Jekyll
4
4
  class Locale::Handler
5
+ attr_writer :current_locale
6
+
5
7
  def initialize(site)
6
8
  @site = site
7
9
  @config = site.config
8
10
  end
9
11
 
10
12
  def reset
11
- @data = nil
13
+ @locale_data = nil
14
+ @portfolio = nil
12
15
  end
13
16
 
14
17
  def data
15
- @data ||= begin
16
- fallback = site.site_data.dig(locales_dir, locale)
17
- return {} unless fallback.is_a?(Hash)
18
+ locale_data[current_locale] || locale_data[default_locale]
19
+ end
18
20
 
19
- # transform hash to one with "latinized lowercased string keys"
20
- Jekyll::Utils.snake_case_keys(fallback)
21
+ def portfolio
22
+ @portfolio ||= (site.docs_to_write + html_pages)
23
+ end
24
+
25
+ def available_locales
26
+ @available_locales ||= begin
27
+ locales = Array(config["available_locales"]) - [default_locale]
28
+ locales.compact!
29
+ locales
21
30
  end
22
31
  end
23
32
 
33
+ def current_locale
34
+ @current_locale ||= default_locale
35
+ end
36
+
37
+ def default_locale
38
+ @default_locale ||= begin
39
+ value = config["locale"]
40
+ value.to_s.empty? ? "en" : value
41
+ end
42
+ end
43
+
44
+ def inspect
45
+ "#<#{self.class} @site=#{site}>"
46
+ end
47
+
24
48
  private
25
49
 
26
50
  attr_reader :site, :config
27
51
 
52
+ def html_pages
53
+ @html_pages ||= begin
54
+ pages = site.site_payload["site"]["html_pages"] || []
55
+ pages.reject { |page| page.name == "404.html" }
56
+ end
57
+ end
58
+
28
59
  def locales_dir
29
60
  @locales_dir ||= begin
30
61
  value = config["locales_dir"]
@@ -32,10 +63,13 @@ module Jekyll
32
63
  end
33
64
  end
34
65
 
35
- def locale
36
- @locale ||= begin
37
- value = config["locale"]
38
- value.to_s.empty? ? "en" : value
66
+ def locale_data
67
+ @locale_data ||= begin
68
+ ldata = site.site_data[locales_dir]
69
+ return {} unless ldata.is_a?(Hash)
70
+
71
+ # transform hash to one with "latinized lowercased string keys"
72
+ Jekyll::Utils.snake_case_keys(ldata)
39
73
  end
40
74
  end
41
75
  end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Jekyll
4
+ class Locale::Page < Page
5
+ extend Forwardable
6
+
7
+ attr_reader :canon, :locale
8
+ attr_accessor :data, :content, :output
9
+
10
+ def_delegators :@canon, :site, :extname, :relative_path
11
+
12
+ def initialize(canon, locale)
13
+ @canon = canon
14
+ @locale = locale
15
+ end
16
+
17
+ def url
18
+ @url ||= File.join(locale, canon.url)
19
+ end
20
+
21
+ def to_liquid
22
+ @to_liquid ||= Locale::PageDrop.new(self)
23
+ end
24
+
25
+ def setup_hreflangs
26
+ @hreflangs = (canon.locale_pages + [canon] - [self]).map do |locale_page|
27
+ {
28
+ "locale" => locale_page.locale || site.locale_handler.default_locale,
29
+ "relation" => locale_page.locale ? "alternate" : "canonical",
30
+ "url" => locale_page.url,
31
+ }
32
+ end
33
+ end
34
+
35
+ def inspect
36
+ "#<#{self.class} @canon=#{canon.inspect} @locale=#{locale.inspect}>"
37
+ end
38
+ alias_method :to_s, :inspect
39
+ end
40
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Jekyll
4
+ class Locale::PageGenerator < Generator
5
+ safe true
6
+ priority :lowest
7
+
8
+ def generate(site)
9
+ @site = site
10
+ handler = site.locale_handler
11
+ return if handler.available_locales.empty?
12
+
13
+ handler.available_locales.each do |locale|
14
+ handler.portfolio.each do |canon_doc|
15
+ locale_page = Locale::Page.new(canon_doc, locale)
16
+ locale_page.content = canon_doc.content
17
+ locale_page.data = canon_doc.data
18
+
19
+ # add locale_page to parent document and base array of pages
20
+ canon_doc.locale_pages << locale_page
21
+ site.pages << locale_page
22
+ end
23
+ end
24
+ end
25
+
26
+ def inspect
27
+ "#<#{self.class} @site=#{@site}>"
28
+ end
29
+ end
30
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Jekyll
4
4
  module Locale
5
- VERSION = "0.1.0"
5
+ VERSION = "0.2.0"
6
6
  end
7
7
  end
@@ -3,13 +3,13 @@
3
3
  module Jekyll
4
4
  class Drops::UnifiedPayloadDrop
5
5
  def locale
6
- @locale ||= Jekyll::Locale::Drop.new(@obj.locale_handler)
6
+ @locale ||= Locale::Drop.new(@obj.locale_handler)
7
7
  end
8
8
  end
9
9
 
10
10
  class Site
11
11
  def locale_handler
12
- @locale_handler ||= Jekyll::Locale::Handler.new(self)
12
+ @locale_handler ||= Locale::Handler.new(self)
13
13
  end
14
14
  end
15
15
  end
@@ -47,7 +47,7 @@ module Jekyll
47
47
 
48
48
  private
49
49
 
50
- # Replace each character sequence with a hyphen.
50
+ # Replace each character sequence with given character.
51
51
  #
52
52
  # See Utils#slugify for a description of the character sequence specified
53
53
  # by each mode.
data/lib/jekyll-locale.rb CHANGED
@@ -3,13 +3,46 @@
3
3
  module Jekyll
4
4
  module Locale
5
5
  autoload :Drop, "jekyll/locale/drop"
6
+ autoload :Page, "jekyll/locale/page"
6
7
  autoload :Handler, "jekyll/locale/handler"
7
8
  end
9
+
10
+ #
11
+
12
+ module LocaleSupport
13
+ attr_reader :locale
14
+
15
+ def hreflangs
16
+ @hreflangs ||= locale_pages.map do |locale_page|
17
+ {
18
+ "locale" => locale_page.locale,
19
+ "relation" => "alternate",
20
+ "url" => locale_page.url,
21
+ }
22
+ end
23
+ end
24
+
25
+ def locale_pages
26
+ @locale_pages ||= []
27
+ end
28
+ end
29
+
30
+ # Enhance Jekyll::Page and Jekyll::Document classes
31
+ [Page, Document].each { |klass| klass.include LocaleSupport }
8
32
  end
9
33
 
34
+ require_relative "jekyll/locale/page_generator"
35
+
10
36
  require_relative "jekyll/patches/site"
11
37
  require_relative "jekyll/patches/utils"
12
38
 
13
39
  Jekyll::Hooks.register :site, :after_reset do |site|
14
40
  site.locale_handler.reset
15
41
  end
42
+
43
+ Jekyll::Hooks.register [:pages, :documents], :pre_render do |document, payload|
44
+ handler = document.site.locale_handler
45
+ handler.current_locale = document.locale
46
+ document.setup_hreflangs if document.is_a?(Jekyll::Locale::Page)
47
+ payload["page"]["hreflangs"] = document.hreflangs
48
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jekyll-locale
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ashwin Maroli
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-09-21 00:00:00.000000000 Z
11
+ date: 2018-09-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: jekyll
@@ -36,6 +36,8 @@ files:
36
36
  - lib/jekyll-locale.rb
37
37
  - lib/jekyll/locale/drop.rb
38
38
  - lib/jekyll/locale/handler.rb
39
+ - lib/jekyll/locale/page.rb
40
+ - lib/jekyll/locale/page_generator.rb
39
41
  - lib/jekyll/locale/version.rb
40
42
  - lib/jekyll/patches/site.rb
41
43
  - lib/jekyll/patches/utils.rb