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.
@@ -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
+
@@ -0,0 +1,6 @@
1
+ module Jekyll
2
+ module MultipleLanguagesPlugin
3
+ VERSION = "1.4.0"
4
+ end
5
+ end
6
+