jekyll-polyglotter 1.4.0.pre.alpha.pre.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE.txt +8 -0
- data/README.md +164 -0
- data/lib/jekyll-polyglotter.rb +1 -0
- data/lib/jekyll/polyglotter.rb +6 -0
- data/lib/jekyll/polyglotter/hooks.rb +3 -0
- data/lib/jekyll/polyglotter/hooks/assets-toggle.rb +7 -0
- data/lib/jekyll/polyglotter/hooks/coordinate.rb +23 -0
- data/lib/jekyll/polyglotter/hooks/process.rb +11 -0
- data/lib/jekyll/polyglotter/liquid.rb +7 -0
- data/lib/jekyll/polyglotter/liquid/tags/i18n-headers.rb +31 -0
- data/lib/jekyll/polyglotter/patches.rb +4 -0
- data/lib/jekyll/polyglotter/patches/jekyll/document.rb +41 -0
- data/lib/jekyll/polyglotter/patches/jekyll/page.rb +33 -0
- data/lib/jekyll/polyglotter/patches/jekyll/site.rb +218 -0
- data/lib/jekyll/polyglotter/patches/jekyll/static_file.rb +21 -0
- data/lib/jekyll/polyglotter/version.rb +5 -0
- metadata +74 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: a3d60f4151f75331cc6d48bd65def65107d2118e17977bddf6b4688c803222f8
|
4
|
+
data.tar.gz: 5719649978b4af4e75a3a5ee62d55da957f40307bab757901068971893925628
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 9f759bf20ace058c9bc234bfdc846e16571dd4ae54157c321a6245003ea394b20eb4151f6f0f8916fea4dc074a5276761531605cef51efa34e407eefcc967c8f
|
7
|
+
data.tar.gz: 65bab4ffef4f2d0d5876cd8f5688f2f5f96fd225e5ad07ee887dd419835906d0dcdf0e6ed7f82299d28e712aa07d766ee6cffad68334dd19abb84dfcd2b3ceb8
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,8 @@
|
|
1
|
+
Copyright (c) 2018 Tnarik Innael
|
2
|
+
Copyright (c) 2015 - 2017 Samuel Volin
|
3
|
+
|
4
|
+
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:
|
5
|
+
|
6
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
7
|
+
|
8
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,164 @@
|
|
1
|
+
Polyglotter
|
2
|
+
---
|
3
|
+
[![Gem Version](https://badge.fury.io/rb/jekyll-polyglotter.svg)](https://badge.fury.io/rb/jekyll-polyglotter)
|
4
|
+
[![Build Status](https://travis-ci.org/tnarik/polyglotter.svg?branch=master)](https://travis-ci.org/tnarik/polyglotter)
|
5
|
+
|
6
|
+
__Polyglotter__ is a fast, painless, open-source internationalization plugin for [Jekyll](http://jekyllrb.com) blogs, based on [Polyglot](http://polyglot.untra.io/). Polyglotter is as easy (easier) to setup and use with any Jekyll project, and it scales to the languages you want to support. With fallback support for missing content (or language isolation), automatic url relativization, and powerful SEO tools, Polyglot allows any multi-language jekyll blog to focus on content without the cruft.
|
7
|
+
|
8
|
+
## Why?
|
9
|
+
Jekyll doesn't provide native support for multi-language blogs. This plugin was forked from [jekyll-polyglot](https://github.com/untra/polyglot), as it was lacking some features and didn't seem to be maintained.
|
10
|
+
|
11
|
+
## Installation
|
12
|
+
Add jekyll-polyglotter to your `Gemfile` if you are using Bundler:
|
13
|
+
|
14
|
+
```Ruby
|
15
|
+
group :jekyll_plugins do
|
16
|
+
gem "jekyll-polyglotter"
|
17
|
+
end
|
18
|
+
```
|
19
|
+
|
20
|
+
Or install the gem manually by doing `gem install jekyll-polyglotter` and specify the plugin using `_config.yml`:
|
21
|
+
```YAML
|
22
|
+
plugins:
|
23
|
+
- jekyll-polyglotter
|
24
|
+
```
|
25
|
+
|
26
|
+
## Configuration
|
27
|
+
In your `_config.yml` file, add the following preferences
|
28
|
+
```YAML
|
29
|
+
languages: ["en", "sv", "de", "fr"]
|
30
|
+
default_lang: "en"
|
31
|
+
exclude_from_localization: ["javascript", "images", "css"]
|
32
|
+
parallel_localization: true
|
33
|
+
```
|
34
|
+
These configuration preferences indicate
|
35
|
+
- what i18n languages you wish to support
|
36
|
+
- what is your default "fallback" language for your content
|
37
|
+
- what root level folders are you excluding from localization
|
38
|
+
- whether to run language processing in parallel or serial
|
39
|
+
|
40
|
+
## How To Use It
|
41
|
+
When adding new posts and pages, add to the YAML front matter:
|
42
|
+
```
|
43
|
+
lang: es
|
44
|
+
```
|
45
|
+
or whatever appropriate [I18n language code](https://developer.chrome.com/webstore/i18n)
|
46
|
+
the page should build for. And you're done. Ideally, when designing your site, you should
|
47
|
+
organize files by their relative urls.
|
48
|
+
|
49
|
+
Polyglotter 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:
|
50
|
+
|
51
|
+
```
|
52
|
+
_posts/2010-03-01-salad-recipes-en.md
|
53
|
+
_posts/2010-03-01-salad-recipes-sv.md
|
54
|
+
_posts/2010-03-01-salad-recipes-fr.md
|
55
|
+
```
|
56
|
+
|
57
|
+
Organized names will generate consistent permalinks when the post is rendered, and polyglot will know to build seperate language versions of
|
58
|
+
the website using only the files with the correct `lang` variable in the front matter.
|
59
|
+
|
60
|
+
In short:
|
61
|
+
* Be consistent with how you name and place your *posts* files
|
62
|
+
* Always give your *pages* permalinks in the frontmatter
|
63
|
+
* Don't overthink it, :wink:
|
64
|
+
|
65
|
+
|
66
|
+
#### Fallback Language Support
|
67
|
+
Lets say you are building your website. You have an `/about/` page written in *english*, *german* and
|
68
|
+
*swedish*. You are also supporting a *french* website, but you never designed a *french* version of your `/about/` page!
|
69
|
+
|
70
|
+
No worries. Polyglotter ensures the sitemap of your *english* site matches your *french* site, matches your *swedish* and *german* sites too. In this case, because you specified a `default_lang` variable in your `_config.yml`, all sites missing their languages' counterparts will fallback to your `default_lang`, so content is preserved across different languages of your site.
|
71
|
+
|
72
|
+
#### Relativized Local Urls
|
73
|
+
No need to meticulously manage anchor tags to link to your correct language. Polyglot modifies how pages get written to the site so your *french* links keep vistors on your *french* blog.
|
74
|
+
```md
|
75
|
+
---
|
76
|
+
title: au sujet de notre entreprise
|
77
|
+
permalink: /about/
|
78
|
+
lang: fr
|
79
|
+
---
|
80
|
+
Nous sommes un restaurant situé à Paris . [Ceci est notre menu.](/menu/)
|
81
|
+
```
|
82
|
+
becomes
|
83
|
+
```html
|
84
|
+
<header class="post-header">
|
85
|
+
<h1 class="post-title">au sujet de notre entreprise</h1>
|
86
|
+
</header>
|
87
|
+
|
88
|
+
<article class="post-content">
|
89
|
+
<p>Nous sommes un restaurant situé à Paris . <a href="/fr/menu/">Ceci est notre menu.</a></p>
|
90
|
+
</article>
|
91
|
+
```
|
92
|
+
Notice the link `<a href="/fr/menu/">...` directs to the french website.
|
93
|
+
|
94
|
+
Even if you are falling back to `default_lang` page, relative links built on the *french* site will
|
95
|
+
still link to *french* pages.
|
96
|
+
|
97
|
+
#### Relativized Absolute Urls
|
98
|
+
If you defined a site `url` in your `_config.yaml`, polyglot will automatically relativize absolute links pointing to your website directory:
|
99
|
+
|
100
|
+
```md
|
101
|
+
---
|
102
|
+
lang: fr
|
103
|
+
---
|
104
|
+
Cliquez [ici]({{site.url}}) pour aller à l'entrée du site.
|
105
|
+
```
|
106
|
+
becomes
|
107
|
+
```html
|
108
|
+
<p>Cliquez <a href="https://mywebsite.com/fr/">ici</a> pour aller à l'entrée du site.
|
109
|
+
```
|
110
|
+
|
111
|
+
#### Disabling Url Relativizing
|
112
|
+
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.
|
113
|
+
|
114
|
+
For example, the following urls will be relativized:
|
115
|
+
|
116
|
+
```html
|
117
|
+
href="http://mywebsite.com/about"
|
118
|
+
href="/about"
|
119
|
+
```
|
120
|
+
|
121
|
+
and the following urls will be left alone:
|
122
|
+
|
123
|
+
```html
|
124
|
+
href=" http://mywebsite.com/about"
|
125
|
+
href=" /about"
|
126
|
+
```
|
127
|
+
|
128
|
+
combine with a [html minifier](https://github.com/digitalsparky/jekyll-minifier) for a polished and production ready website.
|
129
|
+
|
130
|
+
#### Localized site.data
|
131
|
+
|
132
|
+
There are cases when `site.data` localization is required.
|
133
|
+
For instance: you might need to localize `_data/navigation.yml` that holds "navigation menu".
|
134
|
+
In order to localize it, just place language-specific files in `_data/:lang/...` folder, and Polyglot will bring those keys to the top level.
|
135
|
+
|
136
|
+
## How It Works
|
137
|
+
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.
|
138
|
+
|
139
|
+
`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.
|
140
|
+
|
141
|
+
## Features
|
142
|
+
This plugin stands out from other I18n Jekyll plugins:
|
143
|
+
|
144
|
+
- automatically corrects your relative links, keeping your *french* visitors on your *french* website, even when content has to fallback to the `default_lang`.
|
145
|
+
- builds all versions of your website *simultaneously*, allowing big websites to scale efficiently.
|
146
|
+
- provides the liquid tag `{{ site.languages }}` to get an array of your I18n strings.
|
147
|
+
- provides the liquid tag `{{ site.default_lang }}` to get the default_lang I18n string.
|
148
|
+
- 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`.
|
149
|
+
- provides the liquid tag `{{ I18n_Headers https://yourwebsite.com/ }}` to append SEO bonuses to your website.
|
150
|
+
- provides `site.data` localization for efficient rich text replacement.
|
151
|
+
- a creator that will answer all of your questions and issues.
|
152
|
+
|
153
|
+
## SEO Recipes
|
154
|
+
Jekyll-polyglotter uses the same few spectacular [Search Engine Optimization techniques](https://untra.github.io/polyglot/seo) as [Polyglot](http://polyglot.untra.io/) to ensure your Jekyll blog gets the most out of it's multilingual audience. Check them out!
|
155
|
+
|
156
|
+
## Compatibility
|
157
|
+
Currently supports Jekyll 3.0 .
|
158
|
+
Windows users will need to disable parallel_localization on their machines by setting `parallel_localization: false` in the `_config.yml`
|
159
|
+
|
160
|
+
## Copyright
|
161
|
+
|
162
|
+
Copyright (c) Tnarik Innael 2018. License: MIT
|
163
|
+
|
164
|
+
Copyright (c) Samuel Volin 2017. License: MIT
|
@@ -0,0 +1 @@
|
|
1
|
+
require "jekyll/polyglotter"
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# hook to coordinate blog posts and pages into distinct urls,
|
2
|
+
# and remove duplicate multilanguage posts and pages
|
3
|
+
Jekyll::Hooks.register :site, :post_read do |site|
|
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
|
22
|
+
site.pages = site.coordinate_documents(site.pages)
|
23
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
# hook to make a call to process rendered documents,
|
2
|
+
Jekyll::Hooks.register :site, :post_render do |site|
|
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
|
10
|
+
site.process_documents(site.pages)
|
11
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Jekyll
|
2
|
+
module Polyglotter
|
3
|
+
module Liquid
|
4
|
+
class I18nHeadersTag < ::Liquid::Tag
|
5
|
+
def initialize(tag_name, text, tokens)
|
6
|
+
super
|
7
|
+
@url = text
|
8
|
+
@url.strip!
|
9
|
+
@url.chomp! '/'
|
10
|
+
end
|
11
|
+
|
12
|
+
def render(context)
|
13
|
+
site = context.registers[:site]
|
14
|
+
permalink = context.registers[:page]['permalink']
|
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"
|
19
|
+
site.languages.each do |lang|
|
20
|
+
next if lang == site.default_lang
|
21
|
+
i18n += "<link rel=\"alternate\" hreflang=\"#{lang}\" "\
|
22
|
+
"href=\"#{site_url}/#{lang}#{permalink}\"/>\n"
|
23
|
+
end
|
24
|
+
i18n
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
Liquid::Template.register_tag('I18n_Headers', Jekyll::Polyglotter::Liquid::I18nHeadersTag)
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Jekyll
|
2
|
+
|
3
|
+
# Monkey patched to unify the title (remove the language token suffix if there is any)
|
4
|
+
# The language token comes from the Front Matter or the default language
|
5
|
+
class Document
|
6
|
+
def lang
|
7
|
+
data[site.lang_field] || site.default_lang
|
8
|
+
end
|
9
|
+
|
10
|
+
alias_method :read_post_data_orig, :read_post_data
|
11
|
+
def read_post_data
|
12
|
+
read_post_data_orig
|
13
|
+
site.page_lang_vars.each do |v|
|
14
|
+
data[v] ||= lang
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def title_url_regex
|
19
|
+
# File basename matching .{language} -{language} {language}. {language}-
|
20
|
+
regex = "([\.\-]#{lang}[\.\-]?)|([\.\-]?#{lang}[\.\-])"
|
21
|
+
%r{#{regex}}
|
22
|
+
end
|
23
|
+
|
24
|
+
def path_url_regex
|
25
|
+
# Path like bar/{language}/foo , bar.{language}/foo, bar/{language}/fu/foo, bar.{language}/fu/foo
|
26
|
+
regex = "([\/\.]#{lang}[\/]?)"
|
27
|
+
%r{#{regex}}
|
28
|
+
end
|
29
|
+
|
30
|
+
def url
|
31
|
+
unified_title = url_placeholders['title'].gsub(title_url_regex, '')
|
32
|
+
unified_path = url_placeholders['path'].gsub(path_url_regex, '')
|
33
|
+
|
34
|
+
@url ||= URL.new({
|
35
|
+
:template => url_template,
|
36
|
+
:placeholders => url_placeholders.to_h.merge({ 'path' => unified_path, 'title' => unified_title }),
|
37
|
+
:permalink => permalink,
|
38
|
+
}).to_s
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Jekyll
|
2
|
+
|
3
|
+
# Monkey patched to unify the title (remove the language token suffix if there is any)
|
4
|
+
# The language token comes from the Front Matter or the default language
|
5
|
+
class Page
|
6
|
+
def lang
|
7
|
+
data[site.lang_field] || site.default_lang
|
8
|
+
end
|
9
|
+
|
10
|
+
def title_url_regex
|
11
|
+
# File basename matching .{language} -{language} {language}. {language}-
|
12
|
+
regex = "([\.\-]#{lang}[\.\-]?)|([\.\-]?#{lang}[\.\-])"
|
13
|
+
%r{#{regex}}
|
14
|
+
end
|
15
|
+
|
16
|
+
def path_url_regex
|
17
|
+
# Path like /{language}/foo , .{language}/foo
|
18
|
+
regex = "([\/\.]#{lang}[\/]?)"
|
19
|
+
%r{#{regex}}
|
20
|
+
end
|
21
|
+
|
22
|
+
def url
|
23
|
+
unified_title = url_placeholders[:basename].gsub(title_url_regex, '')
|
24
|
+
unified_path = url_placeholders[:path].gsub(path_url_regex, '')
|
25
|
+
|
26
|
+
@url ||= URL.new({
|
27
|
+
:template => template,
|
28
|
+
:placeholders => url_placeholders.merge({ path: unified_path, basename: unified_title }),
|
29
|
+
:permalink => permalink,
|
30
|
+
}).to_s
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,218 @@
|
|
1
|
+
include Process
|
2
|
+
module Jekyll
|
3
|
+
class Site
|
4
|
+
attr_reader :default_lang, :languages, :exclude_from_localization, :lang_vars, :lang_field, :page_lang_vars
|
5
|
+
attr_accessor :file_langs, :active_lang
|
6
|
+
|
7
|
+
def prepare
|
8
|
+
@file_langs = {}
|
9
|
+
fetch_languages
|
10
|
+
@parallel_localization = config.fetch('parallel_localization', true)
|
11
|
+
@exclude_from_localization = config.fetch('exclude_from_localization', [])
|
12
|
+
@isolate_languages = config.fetch('isolate_languages', false)
|
13
|
+
@all_docs = {}
|
14
|
+
@lang_field = config.fetch('lang_field', 'lang')
|
15
|
+
|
16
|
+
end
|
17
|
+
|
18
|
+
def fetch_languages
|
19
|
+
@default_lang = config.fetch('default_lang', 'en')
|
20
|
+
@languages = config.fetch('languages', ['en'])
|
21
|
+
@keep_files += (@languages - [@default_lang])
|
22
|
+
@active_lang = @default_lang
|
23
|
+
@lang_vars = config.fetch('lang_vars', [])
|
24
|
+
@page_lang_vars = config.fetch('page_lang_vars', [])
|
25
|
+
end
|
26
|
+
|
27
|
+
alias_method :process_orig, :process
|
28
|
+
def process
|
29
|
+
prepare
|
30
|
+
all_langs = (@languages + [@default_lang]).uniq
|
31
|
+
if @parallel_localization
|
32
|
+
pids = {}
|
33
|
+
all_langs.each do |lang|
|
34
|
+
pids[lang] = fork do
|
35
|
+
process_language lang
|
36
|
+
end
|
37
|
+
end
|
38
|
+
Signal.trap('INT') do
|
39
|
+
all_langs.each do |lang|
|
40
|
+
puts "Killing #{pids[lang]} : #{lang}"
|
41
|
+
kill('INT', pids[lang])
|
42
|
+
end
|
43
|
+
end
|
44
|
+
all_langs.each do |lang|
|
45
|
+
waitpid pids[lang]
|
46
|
+
detach pids[lang]
|
47
|
+
end
|
48
|
+
else
|
49
|
+
all_langs.each do |lang|
|
50
|
+
process_language lang
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
|
56
|
+
# Unified configuration
|
57
|
+
def description
|
58
|
+
if config.fetch('description', '').is_a?(Hash)
|
59
|
+
@description ||= config['description'].has_key?(active_lang)? config['description'][active_lang] : config['description'][@default_lang]
|
60
|
+
else
|
61
|
+
@description ||= config.fetch('description', '')
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def title
|
66
|
+
if config.fetch('title', '').is_a?(Hash)
|
67
|
+
@title ||= config['title'].has_key?(active_lang)? config['title'][active_lang] : config['title'][@default_lang]
|
68
|
+
else
|
69
|
+
@title ||= config.fetch('title', '')
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
# This allows injecting runtime 'config values' (or site.* liquid tags)
|
74
|
+
alias_method :site_payload_orig, :site_payload
|
75
|
+
def site_payload
|
76
|
+
payload = site_payload_orig
|
77
|
+
payload['site']['default_lang'] = default_lang
|
78
|
+
payload['site']['languages'] = languages
|
79
|
+
payload['site']['active_lang'] = active_lang
|
80
|
+
payload['site']['all_docs'] = @all_docs
|
81
|
+
|
82
|
+
payload['site']['description'] = description
|
83
|
+
payload['site']['title'] = title
|
84
|
+
|
85
|
+
lang_vars.each do |v|
|
86
|
+
payload['site'][v] = active_lang
|
87
|
+
end
|
88
|
+
payload
|
89
|
+
end
|
90
|
+
|
91
|
+
def process_language(lang)
|
92
|
+
@active_lang = lang
|
93
|
+
config['active_lang'] = @active_lang
|
94
|
+
lang_vars.each do |v|
|
95
|
+
config[v] = @active_lang
|
96
|
+
end
|
97
|
+
if @active_lang == @default_lang
|
98
|
+
then process_default_language
|
99
|
+
else process_active_language
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def process_default_language
|
104
|
+
old_include = @include
|
105
|
+
process_orig
|
106
|
+
@include = old_include
|
107
|
+
end
|
108
|
+
|
109
|
+
def process_active_language
|
110
|
+
old_dest = @dest
|
111
|
+
old_exclude = @exclude
|
112
|
+
@file_langs = {}
|
113
|
+
@dest = @dest + '/' + @active_lang
|
114
|
+
@exclude += @exclude_from_localization
|
115
|
+
process_orig
|
116
|
+
@dest = old_dest
|
117
|
+
@exclude = old_exclude
|
118
|
+
end
|
119
|
+
|
120
|
+
# assigns natural permalinks to documents and cascades prioritizing documents with
|
121
|
+
# active_lang languages (except for, optionally, posts and HTML pages)
|
122
|
+
def coordinate_documents(docs)
|
123
|
+
approved = {}
|
124
|
+
docs.each do |doc|
|
125
|
+
lang = doc.data[@lang_field] || @default_lang
|
126
|
+
@all_docs[doc.url] ||= []
|
127
|
+
@all_docs[doc.url] << lang
|
128
|
+
@all_docs[doc.url].uniq!
|
129
|
+
@all_docs[doc.url].sort!
|
130
|
+
|
131
|
+
if @isolate_languages
|
132
|
+
# posts/HTML pages are only approved for the active language (no mixing of languages)
|
133
|
+
next if (doc.is_a?(Jekyll::Document) || doc.is_a?(Jekyll::Page) && doc.html? ) && lang != @active_lang
|
134
|
+
end
|
135
|
+
# otherwise use whatever we have, giving priority to the default and active languages
|
136
|
+
next if @file_langs[doc.url] == @active_lang
|
137
|
+
next if @file_langs[doc.url] == @default_lang && lang != @active_lang
|
138
|
+
approved[doc.url] = doc
|
139
|
+
@file_langs[doc.url] = lang
|
140
|
+
end
|
141
|
+
approved.values
|
142
|
+
end
|
143
|
+
|
144
|
+
# performs any necessary operations on the documents before rendering them
|
145
|
+
def process_documents(docs)
|
146
|
+
# Inject the language token in the URLs (except for the default language)
|
147
|
+
unless @active_lang == @default_lang
|
148
|
+
url = config.fetch('url', false)
|
149
|
+
rel_regex = relative_url_regex
|
150
|
+
abs_regex = absolute_url_regex(url)
|
151
|
+
docs.each do |doc|
|
152
|
+
relativize_urls(doc, rel_regex)
|
153
|
+
if url
|
154
|
+
then relativize_absolute_urls(doc, abs_regex, url)
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
# Remove the language token for the default languages
|
160
|
+
rel_regex = relative_url_regex([@default_lang])
|
161
|
+
abs_regex = absolute_url_regex(url, [@default_lang])
|
162
|
+
docs.each do |doc|
|
163
|
+
unrelativize_urls(doc, rel_regex)
|
164
|
+
if url
|
165
|
+
then unrelativize_absolute_urls(doc, abs_regex, url)
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
# a regex that matches relative urls in a html document
|
171
|
+
# matches href="baseurl/foo/bar-baz" and others like it
|
172
|
+
# avoids matching excluded files
|
173
|
+
def relative_url_regex(langs = [])
|
174
|
+
exclude_regex = ''
|
175
|
+
(@exclude + @languages.reject { |l| langs.include?(l) }).each do |x|
|
176
|
+
exclude_regex += "(?!#{x}\/)"
|
177
|
+
end
|
178
|
+
|
179
|
+
strip_regex = ''
|
180
|
+
langs.each do |x|
|
181
|
+
strip_regex += "(?:#{x}\/)?"
|
182
|
+
end
|
183
|
+
|
184
|
+
%r{href=\"?#{@baseurl}\/#{strip_regex}((?:#{exclude_regex}[^,'\"\s\/?\.#]+\.?)*(?:\/[^\]\[\)\(\"\'\s]*)?)\"}
|
185
|
+
end
|
186
|
+
|
187
|
+
def absolute_url_regex(url, langs = [])
|
188
|
+
exclude_regex = ''
|
189
|
+
(@exclude + @languages.reject { |l| langs.include?(l) }).each do |x|
|
190
|
+
exclude_regex += "(?!#{x}\/)"
|
191
|
+
end
|
192
|
+
|
193
|
+
strip_regex = ''
|
194
|
+
langs.each do |x|
|
195
|
+
strip_regex += "(?:#{x}\/)?"
|
196
|
+
end
|
197
|
+
|
198
|
+
%r{href=\"?#{url}#{@baseurl}\/#{strip_regex}((?:#{exclude_regex}[^,'\"\s\/?\.#]+\.?)*(?:\/[^\]\[\)\(\"\'\s]*)?)\"}
|
199
|
+
end
|
200
|
+
|
201
|
+
def relativize_urls(doc, regex)
|
202
|
+
doc.output.gsub!(regex, "href=\"#{@baseurl}/#{@active_lang}/" + '\1"')
|
203
|
+
end
|
204
|
+
|
205
|
+
def relativize_absolute_urls(doc, regex, url)
|
206
|
+
doc.output.gsub!(regex, "href=\"#{url}#{@baseurl}/#{@active_lang}/" + '\1"')
|
207
|
+
end
|
208
|
+
|
209
|
+
def unrelativize_urls(doc, regex)
|
210
|
+
doc.output.gsub!(regex, "href=\"#{@baseurl}/" + '\1"')
|
211
|
+
end
|
212
|
+
|
213
|
+
def unrelativize_absolute_urls(doc, regex, url)
|
214
|
+
doc.output.gsub!(regex, "href=\"#{url}#{@baseurl}/" + '\1"')
|
215
|
+
end
|
216
|
+
|
217
|
+
end
|
218
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
|
2
|
+
module Jekyll
|
3
|
+
# Alteration to Jekyll StaticFile
|
4
|
+
# provides aliased methods to direct write to skip files
|
5
|
+
# excluded from localization
|
6
|
+
class StaticFile
|
7
|
+
alias_method :write_orig, :write
|
8
|
+
def write(dest)
|
9
|
+
return false if exclude_from_localization?
|
10
|
+
write_orig(dest)
|
11
|
+
end
|
12
|
+
|
13
|
+
def exclude_from_localization?
|
14
|
+
return false if @site.active_lang == @site.default_lang
|
15
|
+
@site.exclude_from_localization.each do |e|
|
16
|
+
return true if relative_path[1..-1].start_with?(e)
|
17
|
+
end
|
18
|
+
false
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
metadata
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: jekyll-polyglotter
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.4.0.pre.alpha.pre.2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Samuel Volin
|
8
|
+
- Tnarik Innael
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2018-07-30 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: jekyll
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
requirements:
|
18
|
+
- - "~>"
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: '3'
|
21
|
+
type: :runtime
|
22
|
+
prerelease: false
|
23
|
+
version_requirements: !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - "~>"
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
version: '3'
|
28
|
+
description: Fast open source i18n plugin for Jekyll blogs.
|
29
|
+
email: tnarik@lecafeautomatique.co.uk
|
30
|
+
executables: []
|
31
|
+
extensions: []
|
32
|
+
extra_rdoc_files: []
|
33
|
+
files:
|
34
|
+
- LICENSE.txt
|
35
|
+
- README.md
|
36
|
+
- lib/jekyll-polyglotter.rb
|
37
|
+
- lib/jekyll/polyglotter.rb
|
38
|
+
- lib/jekyll/polyglotter/hooks.rb
|
39
|
+
- lib/jekyll/polyglotter/hooks/assets-toggle.rb
|
40
|
+
- lib/jekyll/polyglotter/hooks/coordinate.rb
|
41
|
+
- lib/jekyll/polyglotter/hooks/process.rb
|
42
|
+
- lib/jekyll/polyglotter/liquid.rb
|
43
|
+
- lib/jekyll/polyglotter/liquid/tags/i18n-headers.rb
|
44
|
+
- lib/jekyll/polyglotter/patches.rb
|
45
|
+
- lib/jekyll/polyglotter/patches/jekyll/document.rb
|
46
|
+
- lib/jekyll/polyglotter/patches/jekyll/page.rb
|
47
|
+
- lib/jekyll/polyglotter/patches/jekyll/site.rb
|
48
|
+
- lib/jekyll/polyglotter/patches/jekyll/static_file.rb
|
49
|
+
- lib/jekyll/polyglotter/version.rb
|
50
|
+
homepage: https://github.com/tnarik/polyglotter
|
51
|
+
licenses:
|
52
|
+
- MIT
|
53
|
+
metadata: {}
|
54
|
+
post_install_message:
|
55
|
+
rdoc_options: []
|
56
|
+
require_paths:
|
57
|
+
- lib
|
58
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
59
|
+
requirements:
|
60
|
+
- - ">="
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: '0'
|
63
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - ">"
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: 1.3.1
|
68
|
+
requirements: []
|
69
|
+
rubyforge_project:
|
70
|
+
rubygems_version: 2.7.7
|
71
|
+
signing_key:
|
72
|
+
specification_version: 4
|
73
|
+
summary: I18n plugin for Jekyll Blogs
|
74
|
+
test_files: []
|