jekyll-l10n 1.7.0 → 2.0.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/README.md +1 -1
- data/lib/jekyll-l10n/extraction/config_loader.rb +25 -55
- data/lib/jekyll-l10n/extraction/extractor.rb +29 -42
- data/lib/jekyll-l10n/jekyll/generator.rb +38 -40
- data/lib/jekyll-l10n/jekyll/post_write_html_reprocessor.rb +14 -26
- data/lib/jekyll-l10n/jekyll/regeneration_checker.rb +59 -45
- data/lib/jekyll-l10n/jekyll/url_filter.rb +5 -6
- data/lib/jekyll-l10n/po_file/reader.rb +2 -4
- data/lib/jekyll-l10n/translation/page_translation_loader.rb +13 -29
- data/lib/jekyll-l10n/translation/translator.rb +29 -61
- data/lib/jekyll-l10n/utils/page_locales_config.rb +72 -149
- data/lib/jekyll-l10n/utils/site_config_accessor.rb +77 -39
- data/lib/jekyll-l10n/version.rb +1 -1
- data/lib/jekyll-l10n.rb +64 -176
- metadata +15 -1
|
@@ -4,51 +4,25 @@ require_relative '../constants'
|
|
|
4
4
|
|
|
5
5
|
module Jekyll
|
|
6
6
|
module L10n
|
|
7
|
-
#
|
|
7
|
+
# Wraps a `with_locales_data` hash and answers questions about it, filling in
|
|
8
|
+
# the defaults from Constants for anything not set.
|
|
8
9
|
#
|
|
9
|
-
#
|
|
10
|
-
#
|
|
11
|
-
# against expected types and ranges, raising clear errors for invalid configurations.
|
|
10
|
+
# It raises InvalidConfigurationError right away for bad locale codes or bad
|
|
11
|
+
# LibreTranslate settings, so mistakes stop the build early.
|
|
12
12
|
#
|
|
13
|
-
#
|
|
14
|
-
# -
|
|
15
|
-
#
|
|
16
|
-
# -
|
|
13
|
+
# Build it from the right data:
|
|
14
|
+
# - For one page, use SiteConfigAccessor.effective_page_data(page), never raw
|
|
15
|
+
# `page.data`; otherwise the page loses the site defaults.
|
|
16
|
+
# - For site-wide settings, use
|
|
17
|
+
# `{ 'with_locales_data' => SiteConfigAccessor.extract_locales_data(site) }`.
|
|
17
18
|
#
|
|
18
|
-
#
|
|
19
|
-
#
|
|
20
|
-
#
|
|
21
|
-
#
|
|
22
|
-
# - Provide getter methods with sensible defaults
|
|
23
|
-
# - Raise detailed validation errors for invalid configurations
|
|
24
|
-
#
|
|
25
|
-
# @example Minimal configuration
|
|
26
|
-
# ---
|
|
27
|
-
# with_locales: true
|
|
28
|
-
# with_locales_data:
|
|
29
|
-
# locales: [es, fr, pt]
|
|
30
|
-
# ---
|
|
31
|
-
#
|
|
32
|
-
# @example Full configuration with LibreTranslate
|
|
33
|
-
# ---
|
|
34
|
-
# with_locales: true
|
|
35
|
-
# with_locales_data:
|
|
36
|
-
# locales: [es, fr, pt_BR]
|
|
37
|
-
# extract_on_build: true
|
|
38
|
-
# update_compendium: true
|
|
39
|
-
# extraction:
|
|
40
|
-
# translatable_attributes: [title, alt, aria-label]
|
|
41
|
-
# translation:
|
|
42
|
-
# fallback: english
|
|
43
|
-
# libretranslate_enabled: true
|
|
44
|
-
# libretranslate_api_url: "http://localhost:5000/translate"
|
|
45
|
-
# libretranslate_timeout: 300
|
|
46
|
-
# logging:
|
|
47
|
-
# debug: true
|
|
48
|
-
# ---
|
|
19
|
+
# @example
|
|
20
|
+
# config = PageLocalesConfig.new(SiteConfigAccessor.effective_page_data(page))
|
|
21
|
+
# config.locales # => ["es", "fr"]
|
|
22
|
+
# config.fallback_mode # => "english"
|
|
49
23
|
#
|
|
50
24
|
class PageLocalesConfig
|
|
51
|
-
#
|
|
25
|
+
# Shortcuts to the defaults in Constants.
|
|
52
26
|
LOCALE_PATTERN = Constants::LOCALE_PATTERN
|
|
53
27
|
DEFAULT_LOCALES_DIR = Constants::DEFAULT_LOCALES_DIR
|
|
54
28
|
DEFAULT_FALLBACK_MODE = Constants::DEFAULT_FALLBACK_MODE
|
|
@@ -63,18 +37,14 @@ module Jekyll
|
|
|
63
37
|
DEFAULT_LIBRETRANSLATE_FORMAT = Constants::DEFAULT_LIBRETRANSLATE_FORMAT
|
|
64
38
|
|
|
65
39
|
# @!attribute [r] data
|
|
66
|
-
# The
|
|
40
|
+
# The hash this config was built from
|
|
67
41
|
# @return [Hash]
|
|
68
42
|
attr_reader :data
|
|
69
43
|
|
|
70
|
-
#
|
|
71
|
-
#
|
|
72
|
-
#
|
|
73
|
-
#
|
|
74
|
-
#
|
|
75
|
-
# @param page_data [Hash] The Jekyll page data/front matter object
|
|
76
|
-
# @raise [Jekyll::Errors::InvalidConfigurationError] If locale codes are invalid
|
|
77
|
-
# @raise [Jekyll::Errors::InvalidConfigurationError] If LibreTranslate config is invalid
|
|
44
|
+
# @param page_data [Hash] A hash with a `with_locales_data` key, and
|
|
45
|
+
# optionally `path` (used in error messages)
|
|
46
|
+
# @raise [Jekyll::Errors::InvalidConfigurationError] If a locale code or a
|
|
47
|
+
# LibreTranslate setting is invalid
|
|
78
48
|
def initialize(page_data)
|
|
79
49
|
@config = page_data['with_locales_data'] || {}
|
|
80
50
|
@data = page_data
|
|
@@ -84,200 +54,156 @@ module Jekyll
|
|
|
84
54
|
validate_libretranslate!
|
|
85
55
|
end
|
|
86
56
|
|
|
87
|
-
#
|
|
57
|
+
# Locales to translate into. The constructor has already checked each code
|
|
58
|
+
# against LOCALE_PATTERN.
|
|
88
59
|
#
|
|
89
|
-
#
|
|
90
|
-
# if not configured. All returned locales are guaranteed to match ISO 639-1 format,
|
|
91
|
-
# optionally suffixed with an ISO 3166-1 alpha-2 country code.
|
|
92
|
-
#
|
|
93
|
-
# @return [Array<String>] BCP 47 locale codes (e.g., ['es', 'fr', 'pt_BR'])
|
|
60
|
+
# @return [Array<String>] Locale codes such as ["es", "pt_BR"], or []
|
|
94
61
|
def locales
|
|
95
62
|
@config['locales'] || []
|
|
96
63
|
end
|
|
97
64
|
|
|
98
|
-
#
|
|
99
|
-
#
|
|
100
|
-
# Returns the directory specified in `with_locales_data.locales_dir`,
|
|
101
|
-
# or the default "_locales" if not configured.
|
|
102
|
-
#
|
|
103
|
-
# @return [String] The directory path relative to site root
|
|
65
|
+
# @return [String] Directory for PO files, relative to the site source
|
|
104
66
|
def locales_dir
|
|
105
67
|
@config['locales_dir'] || DEFAULT_LOCALES_DIR
|
|
106
68
|
end
|
|
107
69
|
|
|
108
|
-
#
|
|
109
|
-
#
|
|
110
|
-
# @return [Boolean] true if extraction is enabled (default), false if explicitly disabled
|
|
70
|
+
# @return [Boolean] false only when `extract_on_build` is false
|
|
111
71
|
def extract_on_build?
|
|
112
72
|
@config['extract_on_build'] != false
|
|
113
73
|
end
|
|
114
74
|
|
|
115
|
-
#
|
|
75
|
+
# Whether to merge page PO files into the locale compendium. A site-wide
|
|
76
|
+
# setting: read it from the site-wide config, not from a page.
|
|
116
77
|
#
|
|
117
|
-
# @return [Boolean]
|
|
118
|
-
# explicitly disabled
|
|
78
|
+
# @return [Boolean] false only when `update_compendium` is false
|
|
119
79
|
def update_compendium?
|
|
120
80
|
@config['update_compendium'] != false
|
|
121
81
|
end
|
|
122
82
|
|
|
123
|
-
#
|
|
83
|
+
# Whether to print the extraction summary at the end of the build. A
|
|
84
|
+
# site-wide setting: Extractor reads it from the site-wide config.
|
|
124
85
|
#
|
|
125
|
-
# @return [Boolean]
|
|
86
|
+
# @return [Boolean] false only when `logging.show_statistics` is false
|
|
126
87
|
def show_statistics?
|
|
127
88
|
@config.dig('logging', 'show_statistics') != false
|
|
128
89
|
end
|
|
129
90
|
|
|
130
|
-
#
|
|
91
|
+
# Turns on HtmlTranslator's log of each translation lookup for this page.
|
|
131
92
|
#
|
|
132
|
-
# @return [Boolean] true
|
|
93
|
+
# @return [Boolean] true when `logging.debug` is true
|
|
133
94
|
def debug_logging?
|
|
134
95
|
@config.dig('logging', 'debug') == true
|
|
135
96
|
end
|
|
136
97
|
|
|
137
|
-
#
|
|
138
|
-
#
|
|
139
|
-
# Trace logging includes detailed per-entry logs for extraction and translation operations.
|
|
140
|
-
# This is automatically enabled if debug_logging? is true.
|
|
98
|
+
# Turns on per-entry LibreTranslate logging. Those lines go to Jekyll's
|
|
99
|
+
# debug level, so they show only with `jekyll build --verbose`.
|
|
141
100
|
#
|
|
142
|
-
# @return [Boolean] true
|
|
101
|
+
# @return [Boolean] true when `logging.trace` or `logging.debug` is true
|
|
143
102
|
def trace_logging?
|
|
144
103
|
@config.dig('logging', 'trace') == true || debug_logging?
|
|
145
104
|
end
|
|
146
105
|
|
|
147
|
-
#
|
|
148
|
-
#
|
|
149
|
-
# Determines how to handle translations that are not found in PO files.
|
|
150
|
-
# Valid modes: "english" (use original text), "marker" (wrap with markers),
|
|
151
|
-
# "empty" (leave blank).
|
|
106
|
+
# What to show when a string has no translation: "english" (the original
|
|
107
|
+
# text), "marker" (the original text wrapped in markers), or "empty".
|
|
152
108
|
#
|
|
153
|
-
# @return [String] The fallback mode
|
|
109
|
+
# @return [String] The fallback mode
|
|
154
110
|
def fallback_mode
|
|
155
111
|
@config.dig('translation', 'fallback') || DEFAULT_FALLBACK_MODE
|
|
156
112
|
end
|
|
157
113
|
|
|
158
|
-
#
|
|
114
|
+
# HTML attributes whose values are extracted and translated. Defaults to
|
|
115
|
+
# DEFAULT_TRANSLATABLE_ATTRIBUTES.
|
|
159
116
|
#
|
|
160
|
-
#
|
|
161
|
-
# or the default list if not configured (title, alt, aria-label, placeholder,
|
|
162
|
-
# aria-description).
|
|
163
|
-
#
|
|
164
|
-
# @return [Array<String>] List of attribute names to extract
|
|
117
|
+
# @return [Array<String>] Attribute names
|
|
165
118
|
def translatable_attributes
|
|
166
119
|
@config.dig('extraction', 'translatable_attributes') || DEFAULT_TRANSLATABLE_ATTRIBUTES
|
|
167
120
|
end
|
|
168
121
|
|
|
169
|
-
#
|
|
170
|
-
#
|
|
171
|
-
# A page is considered to have localization enabled if at least one locale is configured.
|
|
172
|
-
#
|
|
173
|
-
# @return [Boolean] true if locales list is not empty, false otherwise
|
|
122
|
+
# @return [Boolean] true when at least one locale is configured
|
|
174
123
|
def enabled?
|
|
175
124
|
!locales.empty?
|
|
176
125
|
end
|
|
177
126
|
|
|
178
|
-
#
|
|
127
|
+
# Whether to machine-translate with LibreTranslate. An explicit
|
|
128
|
+
# `libretranslate_enabled` always wins. Without it, only a
|
|
129
|
+
# `libretranslate_api_url` you set yourself turns it on; the default URL
|
|
130
|
+
# does not, so an unconfigured site never tries to reach a server.
|
|
179
131
|
#
|
|
180
|
-
#
|
|
181
|
-
# or if a `libretranslate_api_url` is configured (backward compatibility).
|
|
182
|
-
#
|
|
183
|
-
# @return [Boolean] true if LibreTranslate is enabled and configured
|
|
132
|
+
# @return [Boolean] true if LibreTranslate is enabled
|
|
184
133
|
def libretranslate_enabled?
|
|
185
|
-
# Priority 1: Explicit flag (when set)
|
|
186
134
|
if libretranslate_config.key?('libretranslate_enabled')
|
|
187
135
|
return libretranslate_config['libretranslate_enabled'] == true
|
|
188
136
|
end
|
|
189
137
|
|
|
190
|
-
|
|
191
|
-
|
|
138
|
+
url = libretranslate_config['libretranslate_api_url']
|
|
139
|
+
url.is_a?(String) && !url.strip.empty?
|
|
192
140
|
end
|
|
193
141
|
|
|
194
|
-
#
|
|
195
|
-
#
|
|
196
|
-
# The source locale is the language of the original content being translated.
|
|
197
|
-
# Defaults to "en" (English) if not specified.
|
|
198
|
-
#
|
|
199
|
-
# @return [String] BCP 47 locale code (e.g., 'en', 'fr')
|
|
142
|
+
# @return [String] Locale code of the original content. Defaults to
|
|
143
|
+
# DEFAULT_LIBRETRANSLATE_SOURCE_LOCALE.
|
|
200
144
|
def libretranslate_source_locale
|
|
201
145
|
libretranslate_setting('libretranslate_source_locale', DEFAULT_LIBRETRANSLATE_SOURCE_LOCALE)
|
|
202
146
|
end
|
|
203
147
|
|
|
204
|
-
#
|
|
205
|
-
#
|
|
206
|
-
# Determines how text is passed to LibreTranslate API. Valid values: 'text' or 'html'.
|
|
207
|
-
# HTML format preserves markup and performs better with structured content.
|
|
148
|
+
# How strings are sent to LibreTranslate. "html" keeps inline markup intact.
|
|
208
149
|
#
|
|
209
|
-
# @return [String]
|
|
150
|
+
# @return [String] "text" or "html". Defaults to DEFAULT_LIBRETRANSLATE_FORMAT.
|
|
210
151
|
def libretranslate_format
|
|
211
152
|
libretranslate_setting('libretranslate_format', DEFAULT_LIBRETRANSLATE_FORMAT)
|
|
212
153
|
end
|
|
213
154
|
|
|
214
|
-
#
|
|
155
|
+
# Base URL of the LibreTranslate server, without `/translate`, which
|
|
156
|
+
# LibreTranslator appends. Returning the default here does not turn
|
|
157
|
+
# LibreTranslate on; see {#libretranslate_enabled?}.
|
|
215
158
|
#
|
|
216
|
-
#
|
|
217
|
-
#
|
|
218
|
-
# @return [String] The API URL (default: "http://localhost:5000")
|
|
159
|
+
# @return [String] The URL. Defaults to Constants::DEFAULT_LIBRETRANSLATE_API_URL.
|
|
219
160
|
def libretranslate_api_url
|
|
220
161
|
libretranslate_setting('libretranslate_api_url', Constants::DEFAULT_LIBRETRANSLATE_API_URL)
|
|
221
162
|
end
|
|
222
163
|
|
|
223
|
-
#
|
|
224
|
-
#
|
|
225
|
-
# Some LibreTranslate instances require authentication via API key.
|
|
226
|
-
#
|
|
227
|
-
# @return [String, nil] The API key, or nil if not configured
|
|
164
|
+
# @return [String, nil] API key for servers that require one, or nil
|
|
228
165
|
def libretranslate_api_key
|
|
229
166
|
libretranslate_config['libretranslate_api_key']
|
|
230
167
|
end
|
|
231
168
|
|
|
232
|
-
#
|
|
233
|
-
#
|
|
234
|
-
# @return [Integer] Timeout in seconds (default: 300)
|
|
169
|
+
# @return [Integer] Request timeout in seconds. Defaults to
|
|
170
|
+
# DEFAULT_LIBRETRANSLATE_TIMEOUT.
|
|
235
171
|
def libretranslate_timeout
|
|
236
172
|
libretranslate_setting('libretranslate_timeout', DEFAULT_LIBRETRANSLATE_TIMEOUT)
|
|
237
173
|
end
|
|
238
174
|
|
|
239
|
-
#
|
|
240
|
-
#
|
|
241
|
-
# Controls how many strings are sent to LibreTranslate in a single API request.
|
|
242
|
-
# Larger batches are more efficient but may hit size limits.
|
|
175
|
+
# Strings sent per request. Larger batches mean fewer requests but may
|
|
176
|
+
# exceed the server's size limit.
|
|
243
177
|
#
|
|
244
|
-
# @return [Integer]
|
|
178
|
+
# @return [Integer] Defaults to DEFAULT_LIBRETRANSLATE_BATCH_SIZE.
|
|
245
179
|
def libretranslate_batch_size
|
|
246
180
|
libretranslate_setting('libretranslate_batch_size', DEFAULT_LIBRETRANSLATE_BATCH_SIZE)
|
|
247
181
|
end
|
|
248
182
|
|
|
249
|
-
#
|
|
250
|
-
#
|
|
251
|
-
# @return [Integer] Number of retry attempts (default: 3)
|
|
183
|
+
# @return [Integer] Retries for a failed request. Defaults to
|
|
184
|
+
# DEFAULT_LIBRETRANSLATE_RETRY_ATTEMPTS.
|
|
252
185
|
def libretranslate_retry_attempts
|
|
253
186
|
libretranslate_setting('libretranslate_retry_attempts', DEFAULT_LIBRETRANSLATE_RETRY_ATTEMPTS)
|
|
254
187
|
end
|
|
255
188
|
|
|
256
|
-
#
|
|
257
|
-
#
|
|
258
|
-
# @return [Integer] Delay in seconds (default: 2)
|
|
189
|
+
# @return [Integer] Seconds to wait between retries. Defaults to
|
|
190
|
+
# DEFAULT_LIBRETRANSLATE_RETRY_DELAY.
|
|
259
191
|
def libretranslate_retry_delay
|
|
260
192
|
libretranslate_setting('libretranslate_retry_delay', DEFAULT_LIBRETRANSLATE_RETRY_DELAY)
|
|
261
193
|
end
|
|
262
194
|
|
|
263
|
-
#
|
|
264
|
-
#
|
|
265
|
-
# If true, any API error will halt the translation process. If false, errors are logged
|
|
266
|
-
# but translation continues with other entries.
|
|
195
|
+
# When true, the first API error stops machine translation. When false, the
|
|
196
|
+
# error is logged and the remaining entries are still translated.
|
|
267
197
|
#
|
|
268
|
-
# @return [Boolean]
|
|
269
|
-
# translation continues (default: false)
|
|
198
|
+
# @return [Boolean] Defaults to Constants::DEFAULT_LIBRETRANSLATE_STOP_ON_ERROR.
|
|
270
199
|
def libretranslate_stop_on_error?
|
|
271
200
|
val = libretranslate_config['libretranslate_stop_on_error']
|
|
272
201
|
val.nil? ? Constants::DEFAULT_LIBRETRANSLATE_STOP_ON_ERROR : val != false
|
|
273
202
|
end
|
|
274
203
|
|
|
275
|
-
#
|
|
276
|
-
#
|
|
277
|
-
# Translation progress is logged every N entries translated. Set to 0 to disable
|
|
278
|
-
# progress logging.
|
|
204
|
+
# Log progress after every this many translated entries; 0 turns it off.
|
|
279
205
|
#
|
|
280
|
-
# @return [Integer]
|
|
206
|
+
# @return [Integer] Defaults to DEFAULT_LIBRETRANSLATE_PROGRESS_INTERVAL.
|
|
281
207
|
def libretranslate_progress_interval
|
|
282
208
|
libretranslate_setting('libretranslate_progress_interval', DEFAULT_LIBRETRANSLATE_PROGRESS_INTERVAL)
|
|
283
209
|
end
|
|
@@ -323,19 +249,16 @@ module Jekyll
|
|
|
323
249
|
def validate_libretranslate!
|
|
324
250
|
return unless libretranslate_enabled?
|
|
325
251
|
|
|
326
|
-
# Require URL when enabled
|
|
327
252
|
if libretranslate_api_url.nil? || libretranslate_api_url.empty?
|
|
328
253
|
raise Jekyll::Errors::InvalidConfigurationError,
|
|
329
254
|
'LibreTranslate is enabled but libretranslate_api_url is not configured'
|
|
330
255
|
end
|
|
331
256
|
|
|
332
|
-
# Validate source locale format (ISO 639-1, optionally with ISO 3166-1 alpha-2 country)
|
|
333
257
|
unless LOCALE_PATTERN.match?(libretranslate_source_locale)
|
|
334
258
|
raise Jekyll::Errors::InvalidConfigurationError,
|
|
335
259
|
"Invalid libretranslate_source_locale: #{libretranslate_source_locale}"
|
|
336
260
|
end
|
|
337
261
|
|
|
338
|
-
# Validate format
|
|
339
262
|
return if %w[text html].include?(libretranslate_format)
|
|
340
263
|
|
|
341
264
|
raise Jekyll::Errors::InvalidConfigurationError,
|
|
@@ -2,32 +2,29 @@
|
|
|
2
2
|
|
|
3
3
|
module Jekyll
|
|
4
4
|
module L10n
|
|
5
|
-
#
|
|
5
|
+
# Reads `with_locales_data` settings from the site and its pages.
|
|
6
6
|
#
|
|
7
|
-
#
|
|
8
|
-
#
|
|
9
|
-
#
|
|
7
|
+
# The plugin reads settings in two ways, and this class holds both:
|
|
8
|
+
# - Per-page settings: {.page_locales_data} merges the page's front matter
|
|
9
|
+
# over the `_config.yml` defaults that match the page. Read page settings
|
|
10
|
+
# through it (or {.effective_page_data}), never from `page.data` directly.
|
|
11
|
+
# - Site-wide settings: {.extract_locales_data} returns the first `defaults`
|
|
12
|
+
# entry that has `with_locales_data`, whatever its scope.
|
|
10
13
|
#
|
|
11
|
-
#
|
|
12
|
-
#
|
|
13
|
-
# * Compute the union of all configured locales across site and page front matter
|
|
14
|
-
# * Access site source directory
|
|
15
|
-
# * Access site destination directory
|
|
16
|
-
# * Handle both Jekyll site objects and hash-based doubles
|
|
14
|
+
# Methods that take a site also accept a Hash, so specs can pass a plain
|
|
15
|
+
# hash instead of a Jekyll::Site.
|
|
17
16
|
#
|
|
18
17
|
# @example
|
|
19
|
-
#
|
|
20
|
-
#
|
|
21
|
-
# source = SiteConfigAccessor.source(site)
|
|
22
|
-
# dest = SiteConfigAccessor.dest(site)
|
|
18
|
+
# SiteConfigAccessor.page_locales_data(page)['locales'] # => ["es", "fr"]
|
|
19
|
+
# SiteConfigAccessor.extract_locales_data(site)['update_compendium']
|
|
23
20
|
class SiteConfigAccessor
|
|
24
|
-
#
|
|
21
|
+
# Site-wide `with_locales_data`: the value from the first `defaults` entry
|
|
22
|
+
# that has one, whatever pages it matches. Used for settings that apply
|
|
23
|
+
# to the whole build, such as `update_compendium` and
|
|
24
|
+
# `logging.show_statistics`.
|
|
25
25
|
#
|
|
26
|
-
#
|
|
27
|
-
#
|
|
28
|
-
#
|
|
29
|
-
# @param site [Jekyll::Site, Hash] Jekyll site object or hash double
|
|
30
|
-
# @return [Hash] Localization configuration hash or empty hash if not found
|
|
26
|
+
# @param site [Jekyll::Site, Hash] The site, or a hash in specs
|
|
27
|
+
# @return [Hash] The settings, or {} when no entry has them
|
|
31
28
|
def self.extract_locales_data(site)
|
|
32
29
|
config = site.is_a?(Hash) ? site['config'] : site.config
|
|
33
30
|
defaults = config['defaults'] || []
|
|
@@ -35,20 +32,65 @@ module Jekyll
|
|
|
35
32
|
entry&.dig('values', 'with_locales_data') || {}
|
|
36
33
|
end
|
|
37
34
|
|
|
38
|
-
#
|
|
35
|
+
# The page's `with_locales_data`, merged over the `_config.yml` defaults
|
|
36
|
+
# that match the page.
|
|
39
37
|
#
|
|
40
|
-
#
|
|
41
|
-
# -
|
|
42
|
-
#
|
|
43
|
-
#
|
|
44
|
-
#
|
|
45
|
-
# or no ordinary pages are present.
|
|
38
|
+
# We need this because Jekyll's `page.data` fills in defaults one
|
|
39
|
+
# top-level key at a time: as soon as a page sets any `with_locales_data`
|
|
40
|
+
# key, `page.data` loses all the site defaults for it. This method gives
|
|
41
|
+
# the same result Liquid templates see. Nested hashes merge key by key;
|
|
42
|
+
# lists such as `locales` are replaced, not combined.
|
|
46
43
|
#
|
|
47
|
-
#
|
|
48
|
-
#
|
|
44
|
+
# @param page [Jekyll::Page] The page. Any other object gets only its own value.
|
|
45
|
+
# @return [Hash] The page's settings
|
|
46
|
+
def self.page_locales_data(page)
|
|
47
|
+
own = page.data['with_locales_data']
|
|
48
|
+
own = {} unless own.is_a?(Hash)
|
|
49
|
+
deep_merge(defaults_locales_data_for(page), own)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# Like Jekyll::Utils.deep_merge_hashes: nested hashes merge, and any other
|
|
53
|
+
# value from `override` (lists included) wins. Returns a new hash.
|
|
54
|
+
def self.deep_merge(base, override)
|
|
55
|
+
base.merge(override) do |_key, base_value, override_value|
|
|
56
|
+
if base_value.is_a?(Hash) && override_value.is_a?(Hash)
|
|
57
|
+
deep_merge(base_value, override_value)
|
|
58
|
+
else
|
|
59
|
+
override_value
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
private_class_method :deep_merge
|
|
64
|
+
|
|
65
|
+
# The page's data with `with_locales_data` replaced by
|
|
66
|
+
# {.page_locales_data}. Pass this to PageLocalesConfig.new.
|
|
67
|
+
#
|
|
68
|
+
# @param page [Jekyll::Page] The page
|
|
69
|
+
# @return [Hash] Page data with merged `with_locales_data`
|
|
70
|
+
def self.effective_page_data(page)
|
|
71
|
+
page.data.merge('with_locales_data' => page_locales_data(page))
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# `with_locales_data` from the defaults that match the page, or {} when
|
|
75
|
+
# the page has no site to look them up in (as in some specs).
|
|
76
|
+
def self.defaults_locales_data_for(page)
|
|
77
|
+
return {} unless page.is_a?(Jekyll::Page)
|
|
78
|
+
|
|
79
|
+
site = page.site
|
|
80
|
+
return {} unless site.respond_to?(:frontmatter_defaults)
|
|
81
|
+
|
|
82
|
+
value = site.frontmatter_defaults.all(page.relative_path, :pages)['with_locales_data']
|
|
83
|
+
value.is_a?(Hash) ? value : {}
|
|
84
|
+
end
|
|
85
|
+
private_class_method :defaults_locales_data_for
|
|
86
|
+
|
|
87
|
+
# Every locale the site uses: the site-wide list plus any list a page sets
|
|
88
|
+
# in its front matter. Extraction uses it to skip localized output
|
|
89
|
+
# folders, and the compendium steps use it to cover locales that only one
|
|
90
|
+
# page adds.
|
|
49
91
|
#
|
|
50
|
-
# @param site [Jekyll::Site, Hash]
|
|
51
|
-
# @return [Array<String>] Unique locale codes
|
|
92
|
+
# @param site [Jekyll::Site, Hash] The site, or a hash in specs
|
|
93
|
+
# @return [Array<String>] Unique locale codes
|
|
52
94
|
def self.all_configured_locales(site)
|
|
53
95
|
site_wide_locales = extract_locales_data(site)['locales'] || []
|
|
54
96
|
pages = site.is_a?(Hash) ? site['pages'] : site.pages
|
|
@@ -56,18 +98,14 @@ module Jekyll
|
|
|
56
98
|
(site_wide_locales + page_locales).uniq
|
|
57
99
|
end
|
|
58
100
|
|
|
59
|
-
#
|
|
60
|
-
#
|
|
61
|
-
# @param site [Jekyll::Site, Hash] Jekyll site object or hash double
|
|
62
|
-
# @return [String] Path to site source directory
|
|
101
|
+
# @param site [Jekyll::Site, Hash] The site, or a hash in specs
|
|
102
|
+
# @return [String] The site source directory
|
|
63
103
|
def self.source(site)
|
|
64
104
|
site.is_a?(Hash) ? site['source'] : site.source
|
|
65
105
|
end
|
|
66
106
|
|
|
67
|
-
#
|
|
68
|
-
#
|
|
69
|
-
# @param site [Jekyll::Site, Hash] Jekyll site object or hash double
|
|
70
|
-
# @return [String] Path to site destination directory
|
|
107
|
+
# @param site [Jekyll::Site, Hash] The site, or a hash in specs
|
|
108
|
+
# @return [String] The site destination directory
|
|
71
109
|
def self.dest(site)
|
|
72
110
|
site.is_a?(Hash) ? site['dest'] : site.dest
|
|
73
111
|
end
|
data/lib/jekyll-l10n/version.rb
CHANGED
|
@@ -6,6 +6,6 @@ module Jekyll
|
|
|
6
6
|
# Regenerated alongside the gemspec on every `make jekyll-l10n.gemspec`
|
|
7
7
|
# run (locally or in CI), so it always matches spec.version in the built
|
|
8
8
|
# gem. Any hand edit is overwritten on the next run.
|
|
9
|
-
VERSION = '
|
|
9
|
+
VERSION = '2.0.0'
|
|
10
10
|
end
|
|
11
11
|
end
|