jekyll-locale 0.1.0 → 0.2.0

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
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