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
data/lib/jekyll-l10n.rb
CHANGED
|
@@ -7,167 +7,74 @@ require 'liquid'
|
|
|
7
7
|
require 'nokogiri'
|
|
8
8
|
require 'gettext/po'
|
|
9
9
|
|
|
10
|
-
# # jekyll-l10n:
|
|
11
|
-
#
|
|
12
|
-
#
|
|
13
|
-
#
|
|
14
|
-
#
|
|
15
|
-
#
|
|
16
|
-
# ##
|
|
17
|
-
#
|
|
18
|
-
#
|
|
19
|
-
#
|
|
20
|
-
#
|
|
21
|
-
#
|
|
22
|
-
# -
|
|
23
|
-
#
|
|
24
|
-
# -
|
|
25
|
-
#
|
|
26
|
-
# -
|
|
27
|
-
#
|
|
28
|
-
#
|
|
29
|
-
#
|
|
30
|
-
#
|
|
31
|
-
#
|
|
32
|
-
#
|
|
33
|
-
#
|
|
34
|
-
#
|
|
35
|
-
#
|
|
36
|
-
#
|
|
37
|
-
# -
|
|
38
|
-
#
|
|
39
|
-
#
|
|
40
|
-
#
|
|
41
|
-
#
|
|
42
|
-
#
|
|
43
|
-
#
|
|
44
|
-
#
|
|
45
|
-
#
|
|
46
|
-
#
|
|
47
|
-
#
|
|
48
|
-
#
|
|
49
|
-
#
|
|
50
|
-
# - **HtmlTranslator**: Applies translations to HTML DOM nodes
|
|
51
|
-
# - **PageTranslationLoader**: Loads translations with compendium support
|
|
52
|
-
# - **BlockTextExtractor**: Context-aware text extraction
|
|
53
|
-
# - **LibreTranslator**: LibreTranslate API integration
|
|
54
|
-
#
|
|
55
|
-
# ### 4. PO File Management (`Jekyll::L10n::PoFile`)
|
|
56
|
-
# Manages GNU Gettext PO file operations with caching.
|
|
57
|
-
# - **Manager**: Orchestrates PO file operations and caching
|
|
58
|
-
# - **Reader**: Parses PO files into Ruby objects
|
|
59
|
-
# - **Writer**: Serializes PO entries back to file format
|
|
60
|
-
# - **Merger**: Merges translations from compendium files
|
|
61
|
-
# - **Loader**: Loads and validates PO files
|
|
62
|
-
#
|
|
63
|
-
# ### 5. Utilities (`Jekyll::L10n`)
|
|
64
|
-
# Common utilities supporting all other modules.
|
|
65
|
-
# - **TextNormalizer**: Normalizes whitespace for consistent matching
|
|
66
|
-
# - **TextValidator**: Validates extractable text
|
|
67
|
-
# - **TranslationResolver**: Selects best translation with fallback
|
|
68
|
-
# - **HtmlParser**: DOM parsing with safety guards
|
|
69
|
-
# - **PathBuilder**: Constructs locale-specific file paths
|
|
70
|
-
#
|
|
71
|
-
# ## Configuration
|
|
72
|
-
#
|
|
73
|
-
# Configuration can be specified in Jekyll `_config.yml` or in individual page front matter:
|
|
10
|
+
# # jekyll-l10n: translate a Jekyll site with GNU Gettext PO files
|
|
11
|
+
#
|
|
12
|
+
# For every page with `with_locales: true`, the plugin adds a copy per locale
|
|
13
|
+
# under a locale prefix (`/es/about/`), translates the copy from PO files, and
|
|
14
|
+
# collects the page's English strings into PO files for translators.
|
|
15
|
+
#
|
|
16
|
+
# ## Where things live
|
|
17
|
+
#
|
|
18
|
+
# All classes sit directly in `Jekyll::L10n`. The folders group them by job:
|
|
19
|
+
#
|
|
20
|
+
# - `jekyll/`: hooks into the build. Start with Generator (adds the localized
|
|
21
|
+
# copies), LocalizedPage, PostWriteProcessor, and UrlFilter (Liquid filters).
|
|
22
|
+
# - `translation/`: turns English HTML into translated HTML. Translator,
|
|
23
|
+
# PageTranslationLoader, HtmlTranslator.
|
|
24
|
+
# - `extraction/`: collects strings into PO files after the site is written.
|
|
25
|
+
# Extractor, ExtractionResultSaver, CompendiumMerger, CompendiumTranslator.
|
|
26
|
+
# - `po_file/`: reads, writes, merges, and caches PO files. PoFileManager.
|
|
27
|
+
# - `utils/`: shared helpers. Read settings through SiteConfigAccessor and
|
|
28
|
+
# PageLocalesConfig.
|
|
29
|
+
#
|
|
30
|
+
# ## What happens during a build
|
|
31
|
+
#
|
|
32
|
+
# 1. Generate: Generator adds a LocalizedPage per page and locale. With
|
|
33
|
+
# `jekyll_l10n.incremental` on, it skips copies whose inputs did not change.
|
|
34
|
+
# 2. Render: after Jekyll renders a localized page, a hook below runs
|
|
35
|
+
# Translator on it, using the PO files as they are now.
|
|
36
|
+
# 3. Write: Jekyll writes the site.
|
|
37
|
+
# 4. Post-write: a hook below runs PostWriteProcessor. It extracts strings
|
|
38
|
+
# from every English page, merges them into the locale compendia, runs
|
|
39
|
+
# machine translation if enabled. When that wrote PO files, it translates
|
|
40
|
+
# the localized files again so they include the new translations.
|
|
41
|
+
#
|
|
42
|
+
# ## Settings
|
|
43
|
+
#
|
|
44
|
+
# Localization settings live in `with_locales_data`, in `_config.yml`
|
|
45
|
+
# defaults and page front matter. A page's value is merged over the defaults
|
|
46
|
+
# that match it (SiteConfigAccessor.page_locales_data). A few settings apply
|
|
47
|
+
# to the whole build and come from the first defaults entry instead
|
|
48
|
+
# (SiteConfigAccessor.extract_locales_data). The only build-level setting,
|
|
49
|
+
# `incremental`, lives under the top-level `jekyll_l10n` key.
|
|
74
50
|
#
|
|
75
51
|
# ```yaml
|
|
76
|
-
#
|
|
77
|
-
# -
|
|
78
|
-
#
|
|
79
|
-
#
|
|
80
|
-
#
|
|
81
|
-
#
|
|
82
|
-
#
|
|
83
|
-
#
|
|
84
|
-
#
|
|
85
|
-
#
|
|
86
|
-
# libretranslate_api_url: "https://api.libretranslate.de"
|
|
87
|
-
# logging:
|
|
88
|
-
# debug: false
|
|
52
|
+
# defaults:
|
|
53
|
+
# - scope:
|
|
54
|
+
# type: pages
|
|
55
|
+
# values:
|
|
56
|
+
# with_locales: true
|
|
57
|
+
# with_locales_data:
|
|
58
|
+
# locales: [es, fr]
|
|
59
|
+
#
|
|
60
|
+
# jekyll_l10n:
|
|
61
|
+
# incremental: true
|
|
89
62
|
# ```
|
|
90
63
|
#
|
|
91
|
-
#
|
|
64
|
+
# ## Files
|
|
92
65
|
#
|
|
93
|
-
#
|
|
94
|
-
#
|
|
95
|
-
#
|
|
96
|
-
#
|
|
97
|
-
# locales: [es, fr]
|
|
98
|
-
# ---
|
|
99
|
-
# ```
|
|
100
|
-
#
|
|
101
|
-
# ## Usage Examples
|
|
102
|
-
#
|
|
103
|
-
# ### Enable localization for a page
|
|
104
|
-
#
|
|
105
|
-
# ```markdown
|
|
106
|
-
# ---
|
|
107
|
-
# title: About Us
|
|
108
|
-
# with_locales: true
|
|
109
|
-
# with_locales_data:
|
|
110
|
-
# locales: [es, fr, pt_BR]
|
|
111
|
-
# ---
|
|
112
|
-
# Content here...
|
|
113
|
-
# ```
|
|
66
|
+
# - Compendium, one per locale: `_locales/es.po`. Translators work here.
|
|
67
|
+
# - Page PO file: `_locales/es/<page url>/index.html.po`. Extraction writes
|
|
68
|
+
# it, and the compendium merge deletes it unless `update_compendium` is false.
|
|
69
|
+
# - Output: `_site/es/<page url>/index.html`.
|
|
114
70
|
#
|
|
115
|
-
#
|
|
71
|
+
# ## Liquid example
|
|
116
72
|
#
|
|
117
73
|
# ```liquid
|
|
118
|
-
# <!-- Link with current locale -->
|
|
119
|
-
# <a href="{{ '/about/' | locale_url }}">About</a>
|
|
120
|
-
#
|
|
121
|
-
# <!-- Switch to different locale -->
|
|
122
|
-
# <a href="{{ page.url | switch_locale_url: 'es' }}">Español</a>
|
|
123
|
-
#
|
|
124
|
-
# <!-- Build language switcher -->
|
|
125
74
|
# {% for locale in page.with_locales_data.locales %}
|
|
126
|
-
# <a href="{{ page.url | switch_locale_url: locale }}">
|
|
127
|
-
# {{ locale | upcase }}
|
|
128
|
-
# </a>
|
|
75
|
+
# <a href="{{ page.url | switch_locale_url: locale }}">{{ locale }}</a>
|
|
129
76
|
# {% endfor %}
|
|
130
77
|
# ```
|
|
131
|
-
#
|
|
132
|
-
# ## Build Pipeline
|
|
133
|
-
#
|
|
134
|
-
# 1. **Generate Phase**: Generator creates LocalizedPage instances for each locale
|
|
135
|
-
# 2. **Render Phase**: Jekyll renders all pages (including localized variants)
|
|
136
|
-
# 3. **Post-Render Phase**: Translator hook applies translations to localized pages
|
|
137
|
-
# 4. **Write Phase**: Jekyll writes HTML to disk
|
|
138
|
-
# 5. **Post-Write Phase**: PostWriteProcessor extracts new strings and updates translations
|
|
139
|
-
#
|
|
140
|
-
# ## Translation Workflow Timing
|
|
141
|
-
#
|
|
142
|
-
# The plugin applies translations in two phases:
|
|
143
|
-
#
|
|
144
|
-
# 1. **Initial Build (post_render)**: Localized pages are translated during Jekyll's
|
|
145
|
-
# render phase using existing PO files
|
|
146
|
-
# 2. **Post-Extraction (post_write)**: When new strings are extracted and PO files
|
|
147
|
-
# updated, localized HTML is immediately reprocessed with new translations
|
|
148
|
-
#
|
|
149
|
-
# This dual-phase approach ensures both incremental builds (using cached translations)
|
|
150
|
-
# and immediate translation updates (when new strings are found).
|
|
151
|
-
#
|
|
152
|
-
# ## File Locations
|
|
153
|
-
#
|
|
154
|
-
# - **Source pages**: `src/**/*.md` (marked with `with_locales: true`)
|
|
155
|
-
# - **Page-specific PO files**: `_locales/{locale}/{page_path}.po`
|
|
156
|
-
# - **Compendium PO files**: `_locales/{locale}.po` (shared translations for locale)
|
|
157
|
-
# - **Output**: `_site/[locale]/path/to/page/index.html`
|
|
158
|
-
#
|
|
159
|
-
# ## Terminology
|
|
160
|
-
#
|
|
161
|
-
# - **Source pages**: Pages marked with `with_locales: true` in front matter
|
|
162
|
-
# - **Localized pages**: Generated LocalizedPage instances (marked with `localized: true`)
|
|
163
|
-
# - **Compendium**: Locale-level shared translations at `_locales/{locale}.po`
|
|
164
|
-
# - **Page-specific PO files**: Per-page translations at `_locales/{locale}/{page_path}.po`
|
|
165
|
-
# - **String extraction**: Finding translatable text content and HTML attribute values
|
|
166
|
-
#
|
|
167
|
-
# @see Jekyll::L10n::Generator for page generation
|
|
168
|
-
# @see Jekyll::L10n::Translator for translation application
|
|
169
|
-
# @see Jekyll::L10n::Extractor for string extraction
|
|
170
|
-
# @see Jekyll::L10n::UrlFilter for liquid filters
|
|
171
78
|
|
|
172
79
|
require_relative 'jekyll-l10n/version'
|
|
173
80
|
require_relative 'jekyll-l10n/instrumentation'
|
|
@@ -218,40 +125,21 @@ require_relative 'jekyll-l10n/utils/external_link_icon_preserver'
|
|
|
218
125
|
module Jekyll
|
|
219
126
|
# Main plugin namespace
|
|
220
127
|
module L10n
|
|
221
|
-
#
|
|
222
|
-
#
|
|
223
|
-
# Main plugin module providing GNU Gettext-based translation management
|
|
224
|
-
# with automatic page duplication, HTML string extraction, and translation
|
|
225
|
-
# application. This module serves as the entry point for the plugin and
|
|
226
|
-
# coordinates all localization functionality.
|
|
227
|
-
#
|
|
228
|
-
# Key public APIs:
|
|
229
|
-
# - {Jekyll::L10n::Generator} - Creates locale-prefixed page variants
|
|
230
|
-
# - {Jekyll::L10n::Translator} - Applies translations to localized pages
|
|
231
|
-
# - {Jekyll::L10n::Extractor} - Extracts translatable strings from HTML
|
|
232
|
-
# - {Jekyll::L10n::UrlFilter} - Liquid filters for locale-aware URLs
|
|
233
|
-
#
|
|
234
|
-
# @see lib/jekyll-l10n.rb for complete architecture overview and build pipeline
|
|
235
|
-
|
|
236
|
-
# Include Constants module to provide centralized constant definitions
|
|
128
|
+
# The plugin namespace. See the top of this file for an overview.
|
|
237
129
|
include Constants
|
|
238
130
|
|
|
239
|
-
#
|
|
131
|
+
# Shortcuts to the most used defaults in Constants.
|
|
240
132
|
MIN_TRANSLATABLE_LENGTH = Constants::MIN_TRANSLATABLE_LENGTH
|
|
241
133
|
DEFAULT_LOCALES_DIR = Constants::DEFAULT_LOCALES_DIR
|
|
242
134
|
DEFAULT_FALLBACK_MODE = Constants::DEFAULT_FALLBACK_MODE
|
|
243
135
|
DEFAULT_TRANSLATABLE_ATTRIBUTES = Constants::DEFAULT_TRANSLATABLE_ATTRIBUTES
|
|
244
136
|
|
|
245
|
-
#
|
|
246
|
-
#
|
|
247
|
-
# Walks the HTML document and transforms relative URLs to be locale-aware
|
|
248
|
-
# by adding locale prefixes. Useful for translating internal links in
|
|
249
|
-
# localized pages.
|
|
137
|
+
# Adds the locale prefix to the site's internal links in an HTML string.
|
|
250
138
|
#
|
|
251
|
-
# @param html [String] HTML
|
|
252
|
-
# @param locale [String] Locale code
|
|
253
|
-
# @param baseurl [String]
|
|
254
|
-
# @return [String] HTML with
|
|
139
|
+
# @param html [String] HTML to change
|
|
140
|
+
# @param locale [String] Locale code, e.g. 'es'
|
|
141
|
+
# @param baseurl [String] The site baseurl
|
|
142
|
+
# @return [String] HTML with prefixed links
|
|
255
143
|
# @example
|
|
256
144
|
# html_with_locale_urls = Jekyll::L10n.transform(html, 'es', '/mysite')
|
|
257
145
|
def self.transform(html, locale, baseurl)
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: jekyll-l10n
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version:
|
|
4
|
+
version: 2.0.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Alain Reguera Delgado
|
|
@@ -131,6 +131,20 @@ dependencies:
|
|
|
131
131
|
- - "~>"
|
|
132
132
|
- !ruby/object:Gem::Version
|
|
133
133
|
version: '3.13'
|
|
134
|
+
- !ruby/object:Gem::Dependency
|
|
135
|
+
name: rspec_junit_formatter
|
|
136
|
+
requirement: !ruby/object:Gem::Requirement
|
|
137
|
+
requirements:
|
|
138
|
+
- - "~>"
|
|
139
|
+
- !ruby/object:Gem::Version
|
|
140
|
+
version: '0.6'
|
|
141
|
+
type: :development
|
|
142
|
+
prerelease: false
|
|
143
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
144
|
+
requirements:
|
|
145
|
+
- - "~>"
|
|
146
|
+
- !ruby/object:Gem::Version
|
|
147
|
+
version: '0.6'
|
|
134
148
|
- !ruby/object:Gem::Dependency
|
|
135
149
|
name: simplecov
|
|
136
150
|
requirement: !ruby/object:Gem::Requirement
|