jekyll-multiple-languages-plugin 1.3.0 → 1.4.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 +4 -4
- data/LICENSE.txt +251 -78
- data/README.md +197 -59
- data/lib/jekyll-multiple-languages-plugin.rb +445 -0
- data/lib/plugin/version.rb +6 -0
- metadata +33 -39
- data/.gitignore +0 -21
- data/Gemfile +0 -4
- data/Rakefile +0 -1
- data/example/Gemfile +0 -4
- data/example/LICENSE +0 -21
- data/example/README.md +0 -11
- data/example/_config.yml +0 -8
- data/example/_i18n/en.yml +0 -10
- data/example/_i18n/en/_posts/2013-12-09-example-post.md +0 -15
- data/example/_i18n/en/footer.md +0 -2
- data/example/_i18n/es.yml +0 -10
- data/example/_i18n/es/_posts/2013-12-09-example-post.md +0 -15
- data/example/_i18n/es/footer.md +0 -2
- data/example/_i18n/it.yml +0 -10
- data/example/_i18n/it/_posts/2013-12-09-example-post.md +0 -16
- data/example/_i18n/it/footer.md +0 -2
- data/example/_includes/post.html +0 -40
- data/example/_layouts/default.html +0 -60
- data/example/_layouts/post.html +0 -5
- data/example/_plugins/jekyll-multiple-languages-plugin.rb +0 -1
- data/example/css/main.css +0 -285
- data/example/css/responsive.css +0 -92
- data/example/css/syntax.css +0 -60
- data/example/favicon.ico +0 -0
- data/example/images/cover.jpg +0 -0
- data/example/images/logo.png +0 -0
- data/example/images/sidebar-button.png +0 -0
- data/example/index.html +0 -8
- data/example/scripts/responsive.js +0 -14
- data/jekyll-multiple-languages-plugin.gemspec +0 -23
- data/lib/jekyll/multiple/languages/plugin.rb +0 -208
- data/lib/jekyll/multiple/languages/plugin/version.rb +0 -9
@@ -0,0 +1,445 @@
|
|
1
|
+
=begin
|
2
|
+
|
3
|
+
Jekyll Multiple Languages is an internationalization plugin for Jekyll. It
|
4
|
+
compiles your Jekyll site for one or more languages with a similar approach as
|
5
|
+
Rails does. The different sites will be stored in sub folders with the same name
|
6
|
+
as the language it contains.
|
7
|
+
|
8
|
+
Please visit https://github.com/screeninteraction/jekyll-multiple-languages-plugin
|
9
|
+
for more details.
|
10
|
+
|
11
|
+
=end
|
12
|
+
|
13
|
+
|
14
|
+
|
15
|
+
require_relative "plugin/version"
|
16
|
+
|
17
|
+
module Jekyll
|
18
|
+
|
19
|
+
##############################################################################
|
20
|
+
# class Site
|
21
|
+
##############################################################################
|
22
|
+
class Site
|
23
|
+
|
24
|
+
attr_accessor :parsed_translations # Hash that stores parsed translations read from YAML files.
|
25
|
+
|
26
|
+
alias :process_org :process
|
27
|
+
|
28
|
+
#======================================
|
29
|
+
# process
|
30
|
+
#
|
31
|
+
# Reads Jekyll and plugin configuration parameters set on _config.yml, sets
|
32
|
+
# main parameters and processes the website for each language.
|
33
|
+
#======================================
|
34
|
+
def process
|
35
|
+
# Check if plugin settings are set, if not, set a default or quit.
|
36
|
+
#-------------------------------------------------------------------------
|
37
|
+
self.parsed_translations ||= {}
|
38
|
+
|
39
|
+
self.config['exclude_from_localizations'] ||= []
|
40
|
+
|
41
|
+
if ( !self.config['languages'] or
|
42
|
+
self.config['languages'].empty? or
|
43
|
+
!self.config['languages'].all?
|
44
|
+
)
|
45
|
+
puts 'You must provide at least one language using the "languages" setting on your _config.yml.'
|
46
|
+
|
47
|
+
exit
|
48
|
+
end
|
49
|
+
|
50
|
+
|
51
|
+
# Variables
|
52
|
+
#-------------------------------------------------------------------------
|
53
|
+
|
54
|
+
# Original Jekyll configurations
|
55
|
+
baseurl_org = self.config[ 'baseurl' ] # Baseurl set on _config.yml
|
56
|
+
exclude_org = self.exclude # List of excluded paths
|
57
|
+
dest_org = self.dest # Destination folder where the website is generated
|
58
|
+
|
59
|
+
# Site building only variables
|
60
|
+
languages = self.config['languages'] # List of languages set on _config.yml
|
61
|
+
|
62
|
+
# Site wide plugin configurations
|
63
|
+
self.config['default_lang'] = languages.first # Default language (first language of array set on _config.yml)
|
64
|
+
self.config[ 'lang'] = languages.first # Current language being processed
|
65
|
+
self.config['baseurl_root'] = baseurl_org # Baseurl of website root (without the appended language code)
|
66
|
+
|
67
|
+
|
68
|
+
# Build the website for default language
|
69
|
+
#-------------------------------------------------------------------------
|
70
|
+
puts "Building site for default language: \"#{self.config['lang']}\" to: #{self.dest}"
|
71
|
+
|
72
|
+
process_org
|
73
|
+
|
74
|
+
|
75
|
+
# Build the website for the other languages
|
76
|
+
#-------------------------------------------------------------------------
|
77
|
+
|
78
|
+
# Remove .htaccess file from included files, so it wont show up on translations folders.
|
79
|
+
self.include -= [".htaccess"]
|
80
|
+
|
81
|
+
languages.drop(1).each do |lang|
|
82
|
+
|
83
|
+
# Language specific config/variables
|
84
|
+
@dest = dest_org + "/" + lang
|
85
|
+
self.config['baseurl'] = baseurl_org + "/" + lang
|
86
|
+
self.config['lang'] = lang
|
87
|
+
|
88
|
+
# exclude folders or files from being copied to all the language folders
|
89
|
+
exclude_from_localizations = self.config['exclude_from_localizations']
|
90
|
+
self.exclude = exclude_org + exclude_from_localizations
|
91
|
+
|
92
|
+
puts "Building site for language: \"#{self.config['lang']}\" to: #{self.dest}"
|
93
|
+
|
94
|
+
process_org
|
95
|
+
end
|
96
|
+
|
97
|
+
puts 'Build complete'
|
98
|
+
end
|
99
|
+
|
100
|
+
|
101
|
+
|
102
|
+
if Gem::Version.new(Jekyll::VERSION) < Gem::Version.new("3.0.0")
|
103
|
+
alias :read_posts_org :read_posts
|
104
|
+
|
105
|
+
#======================================
|
106
|
+
# read_posts
|
107
|
+
#======================================
|
108
|
+
def read_posts(dir)
|
109
|
+
translate_posts = !self.config['exclude_from_localizations'].include?("_posts")
|
110
|
+
|
111
|
+
if dir == '' && translate_posts
|
112
|
+
read_posts("_i18n/#{self.config['lang']}/")
|
113
|
+
else
|
114
|
+
read_posts_org(dir)
|
115
|
+
end
|
116
|
+
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
end
|
121
|
+
|
122
|
+
|
123
|
+
|
124
|
+
##############################################################################
|
125
|
+
# class PostReader
|
126
|
+
##############################################################################
|
127
|
+
class PostReader
|
128
|
+
|
129
|
+
if Gem::Version.new(Jekyll::VERSION) >= Gem::Version.new("3.0.0")
|
130
|
+
alias :read_posts_org :read_posts
|
131
|
+
|
132
|
+
#======================================
|
133
|
+
# read_posts
|
134
|
+
#======================================
|
135
|
+
def read_posts(dir)
|
136
|
+
translate_posts = !site.config['exclude_from_localizations'].include?("_posts")
|
137
|
+
if dir == '' && translate_posts
|
138
|
+
read_posts("_i18n/#{site.config['lang']}/")
|
139
|
+
else
|
140
|
+
read_posts_org(dir)
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
|
147
|
+
|
148
|
+
##############################################################################
|
149
|
+
# class Page
|
150
|
+
##############################################################################
|
151
|
+
class Page
|
152
|
+
|
153
|
+
#======================================
|
154
|
+
# permalink
|
155
|
+
#======================================
|
156
|
+
def permalink
|
157
|
+
return nil if data.nil? || data['permalink'].nil?
|
158
|
+
|
159
|
+
if site.config['relative_permalinks']
|
160
|
+
File.join(@dir, data['permalink'])
|
161
|
+
else
|
162
|
+
# Look if there's a permalink overwrite specified for this lang
|
163
|
+
data['permalink_'+site.config['lang']] || data['permalink']
|
164
|
+
end
|
165
|
+
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
|
170
|
+
|
171
|
+
##############################################################################
|
172
|
+
# class Post
|
173
|
+
##############################################################################
|
174
|
+
class Post
|
175
|
+
|
176
|
+
if Gem::Version.new(Jekyll::VERSION) < Gem::Version.new("3.0.0")
|
177
|
+
alias :populate_categories_org :populate_categories
|
178
|
+
|
179
|
+
#======================================
|
180
|
+
# populate_categories
|
181
|
+
#
|
182
|
+
# Monkey patched this method to remove unwanted strings
|
183
|
+
# ("_i18n" and language code) that are prepended to posts categories
|
184
|
+
# because of how the multilingual posts are arranged in subfolders.
|
185
|
+
#======================================
|
186
|
+
def populate_categories
|
187
|
+
categories_from_data = Utils.pluralized_array_from_hash(data, 'category', 'categories')
|
188
|
+
self.categories = (
|
189
|
+
Array(categories) + categories_from_data
|
190
|
+
).map {|c| c.to_s.downcase}.flatten.uniq
|
191
|
+
|
192
|
+
self.categories.delete("_i18n")
|
193
|
+
self.categories.delete(site.config['lang'])
|
194
|
+
|
195
|
+
return self.categories
|
196
|
+
end
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
|
201
|
+
|
202
|
+
##############################################################################
|
203
|
+
# class Document
|
204
|
+
##############################################################################
|
205
|
+
class Document
|
206
|
+
|
207
|
+
if Gem::Version.new(Jekyll::VERSION) >= Gem::Version.new("3.0.0")
|
208
|
+
alias :populate_categories_org :populate_categories
|
209
|
+
|
210
|
+
#======================================
|
211
|
+
# populate_categories
|
212
|
+
#
|
213
|
+
# Monkey patched this method to remove unwanted strings
|
214
|
+
# ("_i18n" and language code) that are prepended to posts categories
|
215
|
+
# because of how the multilingual posts are arranged in subfolders.
|
216
|
+
#======================================
|
217
|
+
def populate_categories
|
218
|
+
data['categories'].delete("_i18n")
|
219
|
+
data['categories'].delete(site.config['lang'])
|
220
|
+
|
221
|
+
merge_data!({
|
222
|
+
'categories' => (
|
223
|
+
Array(data['categories']) + Utils.pluralized_array_from_hash(data, 'category', 'categories')
|
224
|
+
).map(&:to_s).flatten.uniq
|
225
|
+
})
|
226
|
+
end
|
227
|
+
end
|
228
|
+
end
|
229
|
+
|
230
|
+
|
231
|
+
|
232
|
+
#-----------------------------------------------------------------------------
|
233
|
+
#
|
234
|
+
# The next classes implements the plugin Liquid Tags and/or Filters
|
235
|
+
#
|
236
|
+
#-----------------------------------------------------------------------------
|
237
|
+
|
238
|
+
|
239
|
+
##############################################################################
|
240
|
+
# class LocalizeTag
|
241
|
+
#
|
242
|
+
# Localization by getting localized text from YAML files.
|
243
|
+
# User must use the "t" or "translate" liquid tags.
|
244
|
+
##############################################################################
|
245
|
+
class LocalizeTag < Liquid::Tag
|
246
|
+
|
247
|
+
#======================================
|
248
|
+
# initialize
|
249
|
+
#======================================
|
250
|
+
def initialize(tag_name, key, tokens)
|
251
|
+
super
|
252
|
+
@key = key.strip
|
253
|
+
end
|
254
|
+
|
255
|
+
|
256
|
+
|
257
|
+
#======================================
|
258
|
+
# render
|
259
|
+
#======================================
|
260
|
+
def render(context)
|
261
|
+
if "#{context[@key]}" != "" # Check for page variable
|
262
|
+
key = "#{context[@key]}"
|
263
|
+
else
|
264
|
+
key = @key
|
265
|
+
end
|
266
|
+
|
267
|
+
site = context.registers[:site] # Jekyll site object
|
268
|
+
|
269
|
+
lang = site.config['lang']
|
270
|
+
|
271
|
+
unless site.parsed_translations.has_key?(lang)
|
272
|
+
puts "Loading translation from file #{site.source}/_i18n/#{lang}.yml"
|
273
|
+
site.parsed_translations[lang] = YAML.load_file("#{site.source}/_i18n/#{lang}.yml")
|
274
|
+
end
|
275
|
+
|
276
|
+
translation = site.parsed_translations[lang].access(key) if key.is_a?(String)
|
277
|
+
|
278
|
+
if translation.nil? or translation.empty?
|
279
|
+
translation = site.parsed_translations[site.config['default_lang']].access(key)
|
280
|
+
|
281
|
+
puts "Missing i18n key: #{lang}:#{key}"
|
282
|
+
puts "Using translation '%s' from default language: %s" %[translation, site.config['default_lang']]
|
283
|
+
end
|
284
|
+
|
285
|
+
translation
|
286
|
+
end
|
287
|
+
end
|
288
|
+
|
289
|
+
|
290
|
+
|
291
|
+
##############################################################################
|
292
|
+
# class LocalizeInclude
|
293
|
+
#
|
294
|
+
# Localization by including whole files that contain the localization text.
|
295
|
+
# User must use the "tf" or "translate_file" liquid tags.
|
296
|
+
##############################################################################
|
297
|
+
module Tags
|
298
|
+
class LocalizeInclude < IncludeTag
|
299
|
+
|
300
|
+
#======================================
|
301
|
+
# render
|
302
|
+
#======================================
|
303
|
+
def render(context)
|
304
|
+
if "#{context[@file]}" != "" # Check for page variable
|
305
|
+
file = "#{context[@file]}"
|
306
|
+
else
|
307
|
+
file = @file
|
308
|
+
end
|
309
|
+
|
310
|
+
site = context.registers[:site] # Jekyll site object
|
311
|
+
|
312
|
+
includes_dir = File.join(site.source, '_i18n/' + site.config['lang'])
|
313
|
+
|
314
|
+
validate_file_name(file)
|
315
|
+
|
316
|
+
Dir.chdir(includes_dir) do
|
317
|
+
choices = Dir['**/*'].reject { |x| File.symlink?(x) }
|
318
|
+
|
319
|
+
if choices.include?( file)
|
320
|
+
source = File.read(file)
|
321
|
+
partial = Liquid::Template.parse(source)
|
322
|
+
|
323
|
+
context.stack do
|
324
|
+
context['include'] = parse_params( context) if @params
|
325
|
+
contents = partial.render(context)
|
326
|
+
ext = File.extname(file)
|
327
|
+
|
328
|
+
converter = site.converters.find { |c| c.matches(ext) }
|
329
|
+
contents = converter.convert(contents) unless converter.nil?
|
330
|
+
|
331
|
+
contents
|
332
|
+
end
|
333
|
+
else
|
334
|
+
raise IOError.new "Included file '#{file}' not found in #{includes_dir} directory"
|
335
|
+
end
|
336
|
+
|
337
|
+
end
|
338
|
+
end
|
339
|
+
end
|
340
|
+
end
|
341
|
+
|
342
|
+
|
343
|
+
|
344
|
+
##############################################################################
|
345
|
+
# class LocalizeLink
|
346
|
+
#
|
347
|
+
# Creates links or permalinks for translated pages.
|
348
|
+
# User must use the "tl" or "translate_link" liquid tags.
|
349
|
+
##############################################################################
|
350
|
+
class LocalizeLink < Liquid::Tag
|
351
|
+
|
352
|
+
#======================================
|
353
|
+
# initialize
|
354
|
+
#======================================
|
355
|
+
def initialize(tag_name, key, tokens)
|
356
|
+
super
|
357
|
+
@key = key
|
358
|
+
end
|
359
|
+
|
360
|
+
|
361
|
+
|
362
|
+
#======================================
|
363
|
+
# render
|
364
|
+
#======================================
|
365
|
+
def render(context)
|
366
|
+
if "#{context[@key]}" != "" # Check for page variable
|
367
|
+
key = "#{context[@key]}"
|
368
|
+
else
|
369
|
+
key = @key
|
370
|
+
end
|
371
|
+
|
372
|
+
site = context.registers[:site] # Jekyll site object
|
373
|
+
|
374
|
+
key = key.split
|
375
|
+
namespace = key[0]
|
376
|
+
lang = key[1] || site.config[ 'lang']
|
377
|
+
default_lang = site.config['default_lang']
|
378
|
+
baseurl = site.baseurl
|
379
|
+
pages = site.pages
|
380
|
+
url = "";
|
381
|
+
|
382
|
+
if default_lang != lang
|
383
|
+
baseurl = baseurl + "/" + lang
|
384
|
+
end
|
385
|
+
|
386
|
+
for p in pages
|
387
|
+
unless p['namespace'].nil?
|
388
|
+
page_namespace = p['namespace']
|
389
|
+
|
390
|
+
if namespace == page_namespace
|
391
|
+
permalink = p['permalink_'+lang] || p['permalink']
|
392
|
+
url = baseurl + permalink
|
393
|
+
end
|
394
|
+
end
|
395
|
+
end
|
396
|
+
|
397
|
+
url
|
398
|
+
end
|
399
|
+
end
|
400
|
+
|
401
|
+
|
402
|
+
end # End module Jekyll
|
403
|
+
|
404
|
+
|
405
|
+
|
406
|
+
################################################################################
|
407
|
+
# class Hash
|
408
|
+
################################################################################
|
409
|
+
unless Hash.method_defined? :access
|
410
|
+
class Hash
|
411
|
+
|
412
|
+
#======================================
|
413
|
+
# access
|
414
|
+
#======================================
|
415
|
+
def access(path)
|
416
|
+
ret = self
|
417
|
+
|
418
|
+
path.split('.').each do |p|
|
419
|
+
|
420
|
+
if p.to_i.to_s == p
|
421
|
+
ret = ret[p.to_i]
|
422
|
+
else
|
423
|
+
ret = ret[p.to_s] || ret[p.to_sym]
|
424
|
+
end
|
425
|
+
|
426
|
+
break unless ret
|
427
|
+
end
|
428
|
+
|
429
|
+
ret
|
430
|
+
end
|
431
|
+
end
|
432
|
+
end
|
433
|
+
|
434
|
+
|
435
|
+
|
436
|
+
################################################################################
|
437
|
+
# Liquid tags definitions
|
438
|
+
|
439
|
+
Liquid::Template.register_tag('t', Jekyll::LocalizeTag )
|
440
|
+
Liquid::Template.register_tag('translate', Jekyll::LocalizeTag )
|
441
|
+
Liquid::Template.register_tag('tf', Jekyll::Tags::LocalizeInclude)
|
442
|
+
Liquid::Template.register_tag('translate_file', Jekyll::Tags::LocalizeInclude)
|
443
|
+
Liquid::Template.register_tag('tl', Jekyll::LocalizeLink )
|
444
|
+
Liquid::Template.register_tag('translate_link', Jekyll::LocalizeLink )
|
445
|
+
|